@@ -14,6 +14,8 @@ import {
1414 ViewChild ,
1515 ViewChildren ,
1616 ViewContainerRef ,
17+ Directive ,
18+ AfterViewInit ,
1719} from '@angular/core' ;
1820import { ComponentFixture , inject , TestBed } from '@angular/core/testing' ;
1921import { DomPortalOutlet } from './dom-portal-outlet' ;
@@ -404,7 +406,7 @@ describe('Portals', () => {
404406 let componentFactoryResolver : ComponentFactoryResolver ;
405407 let someViewContainerRef : ViewContainerRef ;
406408 let someInjector : Injector ;
407- let someFixture : ComponentFixture < any > ;
409+ let someFixture : ComponentFixture < ArbitraryViewContainerRefComponent > ;
408410 let someDomElement : HTMLElement ;
409411 let host : DomPortalOutlet ;
410412 let injector : Injector ;
@@ -440,6 +442,19 @@ describe('Portals', () => {
440442 expect ( someDomElement . innerHTML ) . toBe ( '' ) ;
441443 } ) ;
442444
445+ it ( 'should move the DOM nodes before running change detection' , ( ) => {
446+ someFixture . detectChanges ( ) ;
447+ let portal = new TemplatePortal ( someFixture . componentInstance . template , someViewContainerRef ) ;
448+
449+ host . attachTemplatePortal ( portal ) ;
450+ someFixture . detectChanges ( ) ;
451+
452+ expect ( someFixture . componentInstance . saveParentNodeOnInit . parentOnViewInit )
453+ . toBe ( someDomElement ) ;
454+
455+ host . dispose ( ) ;
456+ } ) ;
457+
443458 it ( 'should attach and detach a component portal with a given injector' , ( ) => {
444459 let fixture = TestBed . createComponent ( ArbitraryViewContainerRefComponent ) ;
445460 someViewContainerRef = fixture . componentInstance . viewContainerRef ;
@@ -634,12 +649,38 @@ class PizzaMsg {
634649 constructor ( @Optional ( ) public snack : Chocolate ) { }
635650}
636651
652+ /**
653+ * Saves the parent node that the directive was attached to on init.
654+ * Useful to see where the element was in the DOM when it was first attached.
655+ */
656+ @Directive ( {
657+ selector : '[savesParentNodeOnInit]'
658+ } )
659+ class SaveParentNodeOnInit implements AfterViewInit {
660+ parentOnViewInit : HTMLElement ;
661+
662+ constructor ( private _elementRef : ElementRef < HTMLElement > ) { }
663+
664+ ngAfterViewInit ( ) {
665+ this . parentOnViewInit = this . _elementRef . nativeElement . parentElement ! ;
666+ }
667+ }
668+
637669/** Simple component to grab an arbitrary ViewContainerRef */
638670@Component ( {
639671 selector : 'some-placeholder' ,
640- template : '<p>Hello</p>'
672+ template : `
673+ <p>Hello</p>
674+
675+ <ng-template #template>
676+ <div savesParentNodeOnInit></div>
677+ </ng-template>
678+ `
641679} )
642680class ArbitraryViewContainerRefComponent {
681+ @ViewChild ( 'template' , { static : false } ) template : TemplateRef < any > ;
682+ @ViewChild ( SaveParentNodeOnInit , { static : false } ) saveParentNodeOnInit : SaveParentNodeOnInit ;
683+
643684 constructor ( public viewContainerRef : ViewContainerRef , public injector : Injector ) { }
644685}
645686
@@ -731,7 +772,7 @@ const TEST_COMPONENTS = [
731772@NgModule ( {
732773 imports : [ CommonModule , PortalModule ] ,
733774 exports : TEST_COMPONENTS ,
734- declarations : TEST_COMPONENTS ,
775+ declarations : [ ... TEST_COMPONENTS , SaveParentNodeOnInit ] ,
735776 entryComponents : TEST_COMPONENTS ,
736777} )
737778class PortalTestModule { }
0 commit comments