fix(ivy): bindings should be checked in components created dynamically by root component' (#26864)
PR Close #26864
This commit is contained in:
		
							parent
							
								
									aadbc8a9d3
								
							
						
					
					
						commit
						911bfef04c
					
				| @ -421,6 +421,7 @@ function renderComponentOrTemplate<T>( | ||||
|       // Element was stored at 0 in data and directive was stored at 0 in directives
 | ||||
|       // in renderComponent()
 | ||||
|       setHostBindings(getTView(), hostView); | ||||
|       refreshDynamicEmbeddedViews(hostView); | ||||
|       componentRefresh(HEADER_OFFSET, false); | ||||
|     } | ||||
|   } finally { | ||||
| @ -1828,7 +1829,7 @@ export function containerRefreshEnd(): void { | ||||
|  * Goes over dynamic embedded views (ones created through ViewContainerRef APIs) and refreshes them | ||||
|  * by executing an associated template function. | ||||
|  */ | ||||
| function refreshDynamicEmbeddedViews(lViewData: LViewData) { | ||||
| export function refreshDynamicEmbeddedViews(lViewData: LViewData) { | ||||
|   for (let current = getLViewChild(lViewData); current !== null; current = current[NEXT]) { | ||||
|     // Note: current can be an LViewData or an LContainer instance, but here we are only interested
 | ||||
|     // in LContainer. We can tell it's an LContainer because its length is less than the LViewData
 | ||||
|  | ||||
| @ -1771,6 +1771,28 @@ describe('ViewContainerRef', () => { | ||||
| 
 | ||||
|   describe('view engine compatibility', () => { | ||||
| 
 | ||||
|     @Component({selector: 'app', template: ''}) | ||||
|     class AppCmpt { | ||||
|       static ngComponentDef = defineComponent({ | ||||
|         type: AppCmpt, | ||||
|         selectors: [['app']], | ||||
|         factory: () => new AppCmpt( | ||||
|                      directiveInject(ViewContainerRef as any), injectComponentFactoryResolver()), | ||||
|         consts: 0, | ||||
|         vars: 0, | ||||
|         template: (rf: RenderFlags, cmp: AppCmpt) => {} | ||||
|       }); | ||||
| 
 | ||||
|       constructor(private _vcRef: ViewContainerRef, private _cfResolver: ComponentFactoryResolver) { | ||||
|       } | ||||
| 
 | ||||
|       insert(comp: any) { | ||||
|         this._vcRef.createComponent(this._cfResolver.resolveComponentFactory(comp)); | ||||
|       } | ||||
| 
 | ||||
|       clear() { this._vcRef.clear(); } | ||||
|     } | ||||
| 
 | ||||
|     // https://stackblitz.com/edit/angular-xxpffd?file=src%2Findex.html
 | ||||
|     it('should allow injecting VCRef into the root (bootstrapped) component', () => { | ||||
| 
 | ||||
| @ -1781,32 +1803,11 @@ describe('ViewContainerRef', () => { | ||||
|             } | ||||
|           }, 1, 0); | ||||
| 
 | ||||
|       @Component({selector: 'app', template: ''}) | ||||
|       class AppCmpt { | ||||
|         static ngComponentDef = defineComponent({ | ||||
|           type: AppCmpt, | ||||
|           selectors: [['app']], | ||||
|           factory: () => new AppCmpt( | ||||
|                        directiveInject(ViewContainerRef as any), injectComponentFactoryResolver()), | ||||
|           consts: 0, | ||||
|           vars: 0, | ||||
|           template: (rf: RenderFlags, cmp: AppCmpt) => {} | ||||
|         }); | ||||
| 
 | ||||
|         constructor( | ||||
|             private _vcRef: ViewContainerRef, private _cfResolver: ComponentFactoryResolver) {} | ||||
| 
 | ||||
|         insert() { | ||||
|           this._vcRef.createComponent(this._cfResolver.resolveComponentFactory(DynamicComponent)); | ||||
|         } | ||||
| 
 | ||||
|         clear() { this._vcRef.clear(); } | ||||
|       } | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(AppCmpt); | ||||
|       expect(fixture.outerHtml).toBe('<div host="mark"></div>'); | ||||
| 
 | ||||
|       fixture.component.insert(); | ||||
|       fixture.component.insert(DynamicComponent); | ||||
|       fixture.update(); | ||||
|       expect(fixture.outerHtml) | ||||
|           .toBe('<div host="mark"></div><dynamic-cmpt>inserted dynamically</dynamic-cmpt>'); | ||||
| @ -1815,5 +1816,45 @@ describe('ViewContainerRef', () => { | ||||
|       fixture.update(); | ||||
|       expect(fixture.outerHtml).toBe('<div host="mark"></div>'); | ||||
|     }); | ||||
| 
 | ||||
|     it('should check bindings for components dynamically created by root component', () => { | ||||
|       class DynamicCompWithBindings { | ||||
|         checkCount = 0; | ||||
| 
 | ||||
|         ngDoCheck() { this.checkCount++; } | ||||
| 
 | ||||
|         /** check count: {{ checkCount }} */ | ||||
|         static ngComponentDef = defineComponent({ | ||||
|           type: DynamicCompWithBindings, | ||||
|           selectors: [['dynamic-cmpt-with-bindings']], | ||||
|           factory: () => new DynamicCompWithBindings(), | ||||
|           consts: 1, | ||||
|           vars: 1, | ||||
|           template: (rf: RenderFlags, ctx: DynamicCompWithBindings) => { | ||||
|             if (rf & RenderFlags.Create) { | ||||
|               text(0); | ||||
|             } | ||||
|             if (rf & RenderFlags.Update) { | ||||
|               textBinding(0, interpolation1('check count: ', ctx.checkCount, '')); | ||||
|             } | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(AppCmpt); | ||||
|       expect(fixture.outerHtml).toBe('<div host="mark"></div>'); | ||||
| 
 | ||||
|       fixture.component.insert(DynamicCompWithBindings); | ||||
|       fixture.update(); | ||||
|       expect(fixture.outerHtml) | ||||
|           .toBe( | ||||
|               '<div host="mark"></div><dynamic-cmpt-with-bindings>check count: 1</dynamic-cmpt-with-bindings>'); | ||||
| 
 | ||||
|       fixture.update(); | ||||
|       expect(fixture.outerHtml) | ||||
|           .toBe( | ||||
|               '<div host="mark"></div><dynamic-cmpt-with-bindings>check count: 2</dynamic-cmpt-with-bindings>'); | ||||
|     }); | ||||
| 
 | ||||
|   }); | ||||
| }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user