fix(menu): menu content data being cleared when lazy-loaded content is reused between nested triggers (#12476)

Fixes an issue where a nested menu with lazy-loaded that is reused between multiple triggers will clear its content once an alternate trigger is hovered. The issue comes from the fact that we wait for the exit animation to finish before we detach the content, which ends up detaching the content of the new trigger as well.

Fixes #12467.
This commit is contained in:
Kristiyan Kostadinov
2018-08-03 16:08:49 +02:00
committed by Jeremy Elbourn
parent ef57919bd9
commit 1e1751f61e
2 changed files with 13 additions and 3 deletions
+5
View File
@@ -18,6 +18,7 @@ import {
} from '@angular/core';
import {TemplatePortal, DomPortalOutlet} from '@angular/cdk/portal';
import {DOCUMENT} from '@angular/common';
import {Subject} from 'rxjs';
/**
* Menu content that will be rendered lazily once the menu is opened.
@@ -29,6 +30,9 @@ export class MatMenuContent implements OnDestroy {
private _portal: TemplatePortal<any>;
private _outlet: DomPortalOutlet;
/** Emits when the menu content has been attached. */
_attached = new Subject<void>();
constructor(
private _template: TemplateRef<any>,
private _componentFactoryResolver: ComponentFactoryResolver,
@@ -60,6 +64,7 @@ export class MatMenuContent implements OnDestroy {
// risk it staying attached to a pane that's no longer in the DOM.
element.parentNode!.insertBefore(this._outlet.outletElement, element);
this._portal.attach(this._outlet, context);
this._attached.next();
}
/**
+8 -3
View File
@@ -245,9 +245,14 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
if (menu.lazyContent) {
// Wait for the exit animation to finish before detaching the content.
menu._animationDone
.pipe(filter(event => event.toState === 'void'), take(1))
.subscribe(() => {
menu.lazyContent!.detach();
.pipe(
filter(event => event.toState === 'void'),
take(1),
// Interrupt if the content got re-attached.
takeUntil(menu.lazyContent._attached)
)
.subscribe(() => menu.lazyContent!.detach(), undefined, () => {
// No matter whether the content got re-attached, reset the menu.
this._resetMenu();
});
} else {