Skip to content

Commit

Permalink
fix(cdk/portal): not marked as attached when going through specific p…
Browse files Browse the repository at this point in the history
…ortal methods (#22372)

Fixes that the `DomPortalOutlet.hasAttached` doesn't return the correct information when the portal has been attached through the specific portal methods (e.g. `attachComponentPortal`, `attachTemplatePortal`).

Fixes #22370.

(cherry picked from commit 92af5f1)
  • Loading branch information
crisbeto authored and annieyw committed Apr 2, 2021
1 parent 56840c3 commit f387ff6
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/cdk/portal/dom-portal-outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class DomPortalOutlet extends BasePortalOutlet {
// At this point the component has been instantiated, so we move it to the location in the DOM
// where we want it to be rendered.
this.outletElement.appendChild(this._getComponentRootNode(componentRef));
this._attachedPortal = portal;

return componentRef;
}
Expand Down Expand Up @@ -102,6 +103,8 @@ export class DomPortalOutlet extends BasePortalOutlet {
}
}));

this._attachedPortal = portal;

// TODO(jelbourn): Return locals from view.
return viewRef;
}
Expand Down Expand Up @@ -130,6 +133,7 @@ export class DomPortalOutlet extends BasePortalOutlet {

element.parentNode!.insertBefore(anchorNode, element);
this.outletElement.appendChild(element);
this._attachedPortal = portal;

super.setDisposeFn(() => {
// We can't use `replaceWith` here because IE doesn't support it.
Expand Down
1 change: 1 addition & 0 deletions src/cdk/portal/portal-directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ export class CdkPortalOutlet extends BasePortalOutlet implements OnInit, OnDestr
portal.setAttachedHost(this);
element.parentNode!.insertBefore(anchorNode, element);
this._getRootNode().appendChild(element);
this._attachedPortal = portal;

super.setDisposeFn(() => {
if (anchorNode.parentNode) {
Expand Down
28 changes: 27 additions & 1 deletion src/cdk/portal/portal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ describe('Portals', () => {
.not.toBe(initialParent, 'Expected portal to be out of the initial parent on attach.');
expect(hostContainer.contains(innerContent))
.toBe(true, 'Expected content to be inside the outlet on attach.');
expect(testAppComponent.portalOutlet.hasAttached()).toBe(true);

testAppComponent.selectedPortal = undefined;
fixture.detectChanges();
Expand All @@ -109,6 +110,7 @@ describe('Portals', () => {
.toBe(initialParent, 'Expected portal to be back inside initial parent on detach.');
expect(hostContainer.contains(innerContent))
.toBe(false, 'Expected content to be removed from outlet on detach.');
expect(testAppComponent.portalOutlet.hasAttached()).toBe(false);
});

it('should throw when trying to load an element without a parent into a DOM portal', () => {
Expand Down Expand Up @@ -624,6 +626,30 @@ describe('Portals', () => {
expect(() => host.detach()).not.toThrow();
});

it('should set hasAttached when the various portal types are attached', () => {
const fixture = TestBed.createComponent(PortalTestApp);
fixture.detectChanges();
const viewContainerRef = fixture.componentInstance.viewContainerRef;

expect(host.hasAttached()).toBe(false);

host.attachComponentPortal(new ComponentPortal(PizzaMsg, viewContainerRef));
expect(host.hasAttached()).toBe(true);

host.detach();
expect(host.hasAttached()).toBe(false);

host.attachTemplatePortal(
new TemplatePortal(fixture.componentInstance.templateRef, viewContainerRef));
expect(host.hasAttached()).toBe(true);

host.detach();
expect(host.hasAttached()).toBe(false);

host.attachDomPortal(new DomPortal(fixture.componentInstance.domPortalContent));
expect(host.hasAttached()).toBe(true);
});

});
});

Expand Down Expand Up @@ -730,7 +756,7 @@ class PortalTestApp {
fruits = ['Apple', 'Pineapple', 'Durian'];
attachedSpy = jasmine.createSpy('attached spy');

constructor(public injector: Injector) { }
constructor(public viewContainerRef: ViewContainerRef, public injector: Injector) { }

get cakePortal() {
return this.portals.first;
Expand Down

0 comments on commit f387ff6

Please sign in to comment.