-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
feat(menu): support lazy rendering and passing in context data #9271
Conversation
58fb254
to
5e636f9
Compare
src/lib/menu/menu-content.ts
Outdated
const element: HTMLElement = this._template.elementRef.nativeElement; | ||
|
||
// Since the menu might be attached to a different DOM node, we have to re-insert it every time. | ||
element.parentNode!.insertBefore(this._outlet.hostDomElement, element); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite follow why this is necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because we can have the menu be opened by different triggers which in turn have their own OverlayRef
with a different pane. If we didn't do this, the element could end up in limbo if you opened it using two different triggers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add that explanation as a comment?
import {DOCUMENT} from '@angular/common'; | ||
|
||
/** | ||
* Menu content that will be rendered lazily once the menu is opened. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would an end user need to ever interact with this class (i.e. should it be docs-private)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it, because we support providing your own menu instance that matches the MatMenuPanel
interface.
with the `matMenuContent` attribute: | ||
|
||
```html | ||
<mat-menu #appMenu="matMenu"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of avoiding the extra matMenuContent
by letting people add matMenu
to an ng-template
element? Something like
<ng-template matMenu>
...
</ng-template>
The selector for the menu would change to mat-menu, ng-template[matMenu]
. The menu would then optionally inject TemplateRef
and go through the extra steps if one is present.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I was going for initially, but Angular throws an error when you have a component on an ng-template
. The alternative would be to use a directive, but we can't do that either, because we need to wrap the menu content in a div to add the proper styling and for the animation to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just minor comments. Add merge-ready when ready
src/lib/menu/menu-content.ts
Outdated
const element: HTMLElement = this._template.elementRef.nativeElement; | ||
|
||
// Since the menu might be attached to a different DOM node, we have to re-insert it every time. | ||
element.parentNode!.insertBefore(this._outlet.hostDomElement, element); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add that explanation as a comment?
src/cdk/portal/dom-portal-outlet.ts
Outdated
@@ -22,7 +22,8 @@ import {BasePortalOutlet, ComponentPortal, TemplatePortal} from './portal'; | |||
*/ | |||
export class DomPortalOutlet extends BasePortalOutlet { | |||
constructor( | |||
private _hostDomElement: Element, | |||
/** Element into which the content is projected. */ | |||
public hostDomElement: Element, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename this to outletElement
? I think the "host" is leftover from the old class name
5e636f9
to
607d9c8
Compare
607d9c8
to
0a759e0
Compare
@crisbeto passes Google presubmit, just needs rebase |
0a759e0
to
6febb78
Compare
Rebased. |
@crisbeto failing on Travis now |
6febb78
to
7f87d91
Compare
* Introduces the `matMenuContent` directive that allows for menu content to be rendered lazily. * Adds the `matMenuTriggerData` input to the `MatMenuTrigger` that allows for contextual data to be passed in to the lazily-rendered menu panel. This allows for the menu instance to be re-used between triggers. Fixes angular#9251.
7f87d91
to
192be85
Compare
Fixed the test failure. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
matMenuContent
directive that allows for menu content to be rendered lazily.matMenuTriggerData
input to theMatMenuTrigger
that allows for contextual data to be passed in to the lazily-rendered menu panel. This allows for the menu instance to be re-used between triggers.Fixes #9251.