fix(ivy): bindings should be checked in components created dynamically by root component' (#26864)

PR Close #26864
This commit is contained in:
Kara Erickson 2018-10-30 14:38:38 -07:00
parent aadbc8a9d3
commit 911bfef04c
2 changed files with 65 additions and 23 deletions

View File

@ -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

View File

@ -1771,16 +1771,6 @@ describe('ViewContainerRef', () => {
describe('view engine compatibility', () => {
// https://stackblitz.com/edit/angular-xxpffd?file=src%2Findex.html
it('should allow injecting VCRef into the root (bootstrapped) component', () => {
const DynamicComponent =
createComponent('dynamic-cmpt', function(rf: RenderFlags, parent: any) {
if (rf & RenderFlags.Create) {
text(0, 'inserted dynamically');
}
}, 1, 0);
@Component({selector: 'app', template: ''})
class AppCmpt {
static ngComponentDef = defineComponent({
@ -1793,20 +1783,31 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: AppCmpt) => {}
});
constructor(
private _vcRef: ViewContainerRef, private _cfResolver: ComponentFactoryResolver) {}
constructor(private _vcRef: ViewContainerRef, private _cfResolver: ComponentFactoryResolver) {
}
insert() {
this._vcRef.createComponent(this._cfResolver.resolveComponentFactory(DynamicComponent));
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', () => {
const DynamicComponent =
createComponent('dynamic-cmpt', function(rf: RenderFlags, parent: any) {
if (rf & RenderFlags.Create) {
text(0, 'inserted dynamically');
}
}, 1, 0);
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>');
});
});
});