A parent component that contains a @ViewChildren is not returning results for components that are created dynamically.
The container component contains a highlight
directive, and the dynamically generated component contains a highlight
directive within it's template. When queried with @ViewChildren
the query length returns 1. The expected result is 2.
As you can see from the HTML there are definitely two highlight directives on the DOM.
<container-component>
<div></div>
<dynamic-component ng-version="4.0.0">
<div highlight="" style="background-color: yellow;">Dynamic!</div>
</dynamic-component>
<div highlight="" style="background-color: yellow;">Number of Highlights
<div></div>
</div>
</container-component>
Am I missing something?
https://plnkr.co/edit/LilvHJgFjPHnPuaNIKir?p=preview
Container Component
@Component({
selector: 'container-component',
template: `
<div #contentProjection></div>
<div highlight>Number of Highlights {{highlightCount}}<div>
`,
})
export class ContainerComponent implements OnInit, AfterViewInit {
@ViewChildren(HighlightDirective) private highlights: QueryList<HighlightDirective>;
@ViewChild('contentProjection', { read: ViewContainerRef }) private contentProjection: ViewContainerRef;
constructor(
private resolver: ComponentFactoryResolver
) {
}
ngOnInit() {
this.createDynamicComponent();
}
ngAfterViewInit() {
console.log(this.highlights.length);
// Should update with any DOM changes
this.highlights.changes.subscribe(x => {
console.log(this.highlights.length);
});
}
private createDynamicComponent(){
const componentFactory = this.resolver.resolveComponentFactory(DynamicComponent);
this.contentProjection.createComponent(componentFactory);
}
}
Dynamic Component
@Component({
selector: 'dynamic-component',
template: `
<div highlight>Dynamic!</div>
`,
})
export class DynamicComponent {
}
Highlight Directive
@Directive({
selector: '[highlight]'
})
export class HighlightDirective {
constructor(private elementRef: ElementRef) {
elementRef.nativeElement.style.backgroundColor = 'yellow';
}
}
The ViewChild or ViewChildren decorators are used to Query and get the reference of the DOM element in the Component. ViewChild returns the first matching element and ViewChildren returns all the matching elements as a QueryList of items. We can use these references to manipulate element properties in the component.
We can use the @ViewChildren decorator to grab elements from the host view. The @ViewChildren decorator supports directive or component type as parameter, or the name of a template variable. When the parameter is a component/directive the return value will be the component/directive instance.
ViewContainerRef represents a container where one or more views can be attached. The first thing to mention here is that any DOM element can be used as a view container. What's interesting is that Angular doesn't insert views inside the element, but appends them after the element bound to ViewContainer .
That doesn't work because @ViewChildren
only queries its own view, not the view contained within child components. Your dynamic component is a child component that has its own view.
To get around this you could add a @ViewChildren
query in the dynamic component that has an output event to let anyone who cares (your parent component) know that a new instance exists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With