Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cdk-experimental/menu): do not allow two separate triggers to open the same menu #20300

Merged

Conversation

andy9775
Copy link
Contributor

Fixes the error where two different menu triggers open the same menu which leads to open menus not
closing out on hover and other inconsistent behaviour. Opt to throw and error and not allow two
triggers to share a menu.

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Aug 13, 2020
@@ -140,7 +148,7 @@ export class CdkMenuItemTrigger implements OnDestroy {
*/
_toggleOnMouseEnter() {
const menuStack = this._getMenuStack();
if (!menuStack.isEmpty() && !this.isMenuOpen()) {
if (!menuStack?.isEmpty() && !this.isMenuOpen()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first part of this expression is a little hard to parse. Is there a way to make it clearer?

@@ -206,10 +214,10 @@ export class CdkMenuItemTrigger implements OnDestroy {
// that means that the parent menu is a menu bar since we don't put the menu bar on the
// stack
const isParentMenuBar =
!menuStack.closeSubMenuOf(this._parentMenu) && menuStack.peek() !== this._parentMenu;
!menuStack?.closeSubMenuOf(this._parentMenu) && menuStack?.peek() !== this._parentMenu;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you verify that your calls to methods on menuStack? will work in an expected way if menuStack is not defined?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the instance that there is no menustack there's nothing to do and the ? prevents the methods from being called.

@@ -108,6 +110,10 @@ export class CdkContextMenuTrigger implements OnDestroy {
return this._menuPanel;
}
set menuPanel(panel: CdkMenuPanel) {
// If the provided panel already has a stack, that means it already has a trigger configured
if (panel._menuStack && isDevMode()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes a difference, but conventionally the isDevMode check goes first

@@ -108,6 +110,10 @@ export class CdkContextMenuTrigger implements OnDestroy {
return this._menuPanel;
}
set menuPanel(panel: CdkMenuPanel) {
// If the provided panel already has a stack, that means it already has a trigger configured
if (panel._menuStack && isDevMode()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the isDevMode calls will become lint errors with #20146. I suspect that your changes will land first though.

Copy link
Contributor Author

@andy9775 andy9775 Aug 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya, I saw that and wasn't sure how to address it. I think I'll issue a follow up PR after it lands and I'll add a TODO for now

});

it('should throw an error if a trigger in a submenu references its parent menu', () => {
expect(createComponent(TriggerOpensItsMenu)).toThrowError();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be testing for the specific error that we're expecting here? E.g. .toThrowError(/CdkMenuPanel is already referenced by different CdkMenuTrigger/).

@@ -125,7 +125,7 @@ export class CdkMenuItem implements FocusableOption, FocusableElement, OnDestroy
}

// don't set the tabindex if there are no open sibling or parent menus
if (!event || (event && !this._getMenuStack().isEmpty())) {
if (!event || (event && !this._getMenuStack()?.isEmpty())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the event && here is redundant since it's assumed by the !event being true before.

@andy9775 andy9775 force-pushed the cdk-menu-fix-double-trigger-for-menu branch from e4ed617 to be0bf4a Compare August 17, 2020 16:06
@andy9775
Copy link
Contributor Author

@jelbourn @teflonwaffles @crisbeto feedback should be addressed

…n the same menu

Fixes the error where two different menu triggers open the same menu which leads to open menus not
closing out on hover and other inconsistent behaviour. Opt to throw and error and not allow two
triggers to share a menu.
@andy9775 andy9775 force-pushed the cdk-menu-fix-double-trigger-for-menu branch from be0bf4a to 8eb7939 Compare August 17, 2020 16:12
@jelbourn jelbourn added the target: minor This PR is targeted for the next minor release label Aug 17, 2020
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn added action: merge The PR is ready for merge by the caretaker merge safe labels Aug 17, 2020
Copy link
Member

@crisbeto crisbeto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wagnermaciel wagnermaciel merged commit 6948186 into angular:master Aug 18, 2020
@JonWallsten
Copy link

@andy9775: Is this going to affect the Material Menu and Material Menu Trigger as well? We are actually using two different triggers for the same menu with with a purpose. We have the classic tre-dot-menu but also show the menu when using right-click, only then we want the menu to appear where user is clicking. Since the easiest way to get the menu position to be where you click at is to place a trigger there, we have another trigger for that. With only one trigger we would have to move the dots to where the mouse is. Which obviously doesn't look that good.
Worst case, could this feature be optional?

@andy9775
Copy link
Contributor Author

@JonWallsten this pr only impacts the cdk-experimental/menu package and not material.

@jelbourn
Copy link
Member

@JonWallsten in terms of the future- I want to attempt to land a change in Angular that would make this restriction unnecessary before changing the interns of MatMenu

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 18, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants