@@ -17,7 +17,8 @@ import {checkAndUpdateQuery, createQuery} from './query';
1717import { createTemplateData , createViewContainerData } from './refs' ;
1818import { checkAndUpdateTextDynamic , checkAndUpdateTextInline , createText } from './text' ;
1919import { ArgumentType , CheckType , ElementData , NodeData , NodeDef , NodeFlags , ProviderData , RootData , Services , ViewData , ViewDefinition , ViewFlags , ViewHandleEventFn , ViewState , ViewUpdateFn , asElementData , asQueryList , asTextData } from './types' ;
20- import { NOOP , checkBindingNoChanges , isComponentView , resolveViewDefinition } from './util' ;
20+ import { NOOP , checkBindingNoChanges , isComponentView , markParentViewsForCheckProjectedViews , resolveViewDefinition } from './util' ;
21+ import { detachProjectedView } from './view_attach' ;
2122
2223export function viewDef (
2324 flags : ViewFlags , nodes : NodeDef [ ] , updateDirectives ?: ViewUpdateFn ,
@@ -314,12 +315,14 @@ function createViewNodes(view: ViewData) {
314315}
315316
316317export function checkNoChangesView ( view : ViewData ) {
318+ markProjectedViewsForCheck ( view ) ;
317319 Services . updateDirectives ( view , CheckType . CheckNoChanges ) ;
318320 execEmbeddedViewsAction ( view , ViewAction . CheckNoChanges ) ;
319321 Services . updateRenderer ( view , CheckType . CheckNoChanges ) ;
320322 execComponentViewsAction ( view , ViewAction . CheckNoChanges ) ;
321323 // Note: We don't check queries for changes as we didn't do this in v2.x.
322324 // TODO(tbosch): investigate if we can enable the check again in v5.x with a nicer error message.
325+ view . state &= ~ ( ViewState . CheckProjectedViews | ViewState . CheckProjectedView ) ;
323326}
324327
325328export function checkAndUpdateView ( view : ViewData ) {
@@ -329,6 +332,7 @@ export function checkAndUpdateView(view: ViewData) {
329332 } else {
330333 view . state &= ~ ViewState . FirstCheck ;
331334 }
335+ markProjectedViewsForCheck ( view ) ;
332336 Services . updateDirectives ( view , CheckType . CheckAndUpdate ) ;
333337 execEmbeddedViewsAction ( view , ViewAction . CheckAndUpdate ) ;
334338 execQueriesAction (
@@ -343,14 +347,14 @@ export function checkAndUpdateView(view: ViewData) {
343347 execComponentViewsAction ( view , ViewAction . CheckAndUpdate ) ;
344348 execQueriesAction (
345349 view , NodeFlags . TypeViewQuery , NodeFlags . DynamicQuery , CheckType . CheckAndUpdate ) ;
346-
347350 callLifecycleHooksChildrenFirst (
348351 view , NodeFlags . AfterViewChecked |
349352 ( view . state & ViewState . FirstCheck ? NodeFlags . AfterViewInit : 0 ) ) ;
350353
351354 if ( view . def . flags & ViewFlags . OnPush ) {
352355 view . state &= ~ ViewState . ChecksEnabled ;
353356 }
357+ view . state &= ~ ( ViewState . CheckProjectedViews | ViewState . CheckProjectedView ) ;
354358}
355359
356360export function checkAndUpdateNode (
@@ -363,6 +367,31 @@ export function checkAndUpdateNode(
363367 }
364368}
365369
370+ function markProjectedViewsForCheck ( view : ViewData ) {
371+ const def = view . def ;
372+ if ( ! ( def . nodeFlags & NodeFlags . ProjectedTemplate ) ) {
373+ return ;
374+ }
375+ for ( let i = 0 ; i < def . nodes . length ; i ++ ) {
376+ const nodeDef = def . nodes [ i ] ;
377+ if ( nodeDef . flags & NodeFlags . ProjectedTemplate ) {
378+ const projectedViews = asElementData ( view , i ) . template . _projectedViews ;
379+ if ( projectedViews ) {
380+ for ( let i = 0 ; i < projectedViews . length ; i ++ ) {
381+ const projectedView = projectedViews [ i ] ;
382+ projectedView . state |= ViewState . CheckProjectedView ;
383+ markParentViewsForCheckProjectedViews ( projectedView , view ) ;
384+ }
385+ }
386+ } else if ( ( nodeDef . childFlags & NodeFlags . ProjectedTemplate ) === 0 ) {
387+ // a parent with leafs
388+ // no child is a component,
389+ // then skip the children
390+ i += nodeDef . childCount ;
391+ }
392+ }
393+ }
394+
366395function checkAndUpdateNodeInline (
367396 view : ViewData , nodeDef : NodeDef , v0 ?: any , v1 ?: any , v2 ?: any , v3 ?: any , v4 ?: any , v5 ?: any ,
368397 v6 ?: any , v7 ?: any , v8 ?: any , v9 ?: any ) : boolean {
@@ -474,6 +503,7 @@ export function destroyView(view: ViewData) {
474503 view . disposables [ i ] ( ) ;
475504 }
476505 }
506+ detachProjectedView ( view ) ;
477507 if ( view . renderer . destroyNode ) {
478508 destroyViewNodes ( view ) ;
479509 }
@@ -498,7 +528,9 @@ function destroyViewNodes(view: ViewData) {
498528enum ViewAction {
499529 CreateViewNodes ,
500530 CheckNoChanges ,
531+ CheckNoChangesProjectedViews ,
501532 CheckAndUpdate ,
533+ CheckAndUpdateProjectedViews ,
502534 Destroy
503535}
504536
@@ -547,18 +579,44 @@ function callViewAction(view: ViewData, action: ViewAction) {
547579 const viewState = view . state ;
548580 switch ( action ) {
549581 case ViewAction . CheckNoChanges :
550- if ( ( viewState & ViewState . CatDetectChanges ) === ViewState . CatDetectChanges &&
551- ( viewState & ViewState . Destroyed ) === 0 ) {
552- checkNoChangesView ( view ) ;
582+ if ( ( viewState & ViewState . Destroyed ) === 0 ) {
583+ if ( ( viewState & ViewState . CatDetectChanges ) === ViewState . CatDetectChanges ) {
584+ checkNoChangesView ( view ) ;
585+ } else if ( viewState & ViewState . CheckProjectedViews ) {
586+ execProjectedViewsAction ( view , ViewAction . CheckNoChangesProjectedViews ) ;
587+ }
588+ }
589+ break ;
590+ case ViewAction . CheckNoChangesProjectedViews :
591+ if ( ( viewState & ViewState . Destroyed ) === 0 ) {
592+ if ( viewState & ViewState . CheckProjectedView ) {
593+ checkNoChangesView ( view ) ;
594+ } else if ( viewState & ViewState . CheckProjectedViews ) {
595+ execProjectedViewsAction ( view , action ) ;
596+ }
553597 }
554598 break ;
555599 case ViewAction . CheckAndUpdate :
556- if ( ( viewState & ViewState . CatDetectChanges ) === ViewState . CatDetectChanges &&
557- ( viewState & ViewState . Destroyed ) === 0 ) {
558- checkAndUpdateView ( view ) ;
600+ if ( ( viewState & ViewState . Destroyed ) === 0 ) {
601+ if ( ( viewState & ViewState . CatDetectChanges ) === ViewState . CatDetectChanges ) {
602+ checkAndUpdateView ( view ) ;
603+ } else if ( viewState & ViewState . CheckProjectedViews ) {
604+ execProjectedViewsAction ( view , ViewAction . CheckAndUpdateProjectedViews ) ;
605+ }
606+ }
607+ break ;
608+ case ViewAction . CheckAndUpdateProjectedViews :
609+ if ( ( viewState & ViewState . Destroyed ) === 0 ) {
610+ if ( viewState & ViewState . CheckProjectedView ) {
611+ checkAndUpdateView ( view ) ;
612+ } else if ( viewState & ViewState . CheckProjectedViews ) {
613+ execProjectedViewsAction ( view , action ) ;
614+ }
559615 }
560616 break ;
561617 case ViewAction . Destroy :
618+ // Note: destroyView recurses over all views,
619+ // so we don't need to special case projected views here.
562620 destroyView ( view ) ;
563621 break ;
564622 case ViewAction . CreateViewNodes :
@@ -567,6 +625,11 @@ function callViewAction(view: ViewData, action: ViewAction) {
567625 }
568626}
569627
628+ function execProjectedViewsAction ( view : ViewData , action : ViewAction ) {
629+ execEmbeddedViewsAction ( view , action ) ;
630+ execComponentViewsAction ( view , action ) ;
631+ }
632+
570633function execQueriesAction (
571634 view : ViewData , queryFlags : NodeFlags , staticDynamicQueryFlag : NodeFlags ,
572635 checkType : CheckType ) {
0 commit comments