问题
I have a component that uses content projection.
<ng-content select="button">
</ng-content>
I want to do something like this in my component:
@ContentChild('button') button: ElementRef;
However, when I check this.button
, it is undefined
both in ngAfterViewInit
and ngAfterContentInit
.
How can I select my content child if it is a native element and not a custom component?
回答1:
None of the query decorators can select native elements without a reference.
@ViewChild('button')
@ViewChildren('button')
@ContentChild('button')
@ContentChildren('button')
It is not a CSS selector.
The query decorators search the dependency graph for a matching type and select those. A matching type can be a template reference, component or directive.
The recommended approach for selecting specific elements in content is to tag it with a directive.
@Directive({...})
export class MyButtonDirective {}
Now you can query this in your parent component.
@ContentChild(MyButtonDirective) button: MyButtonDirective;
When you use a string value it refers to a template variable reference. Those are written as #someValue
and they can be a template ref, component or directive.
<button #myButton></button>
You can now reference the above as
@ViewChild('myButton')
I do not know if this works for ContentChild
because of the way views work. A #myButton
template variable might not be visible in the parent's dependency graph.
Alternatively, you can inject the ElementRef
of the parent component and then use native JavaScript to search for the children you're seeking. This is a bad practice from an Angular perspective, because the idea is to separate your application from the DOM.
回答2:
The important thing to understand is that the selector you pass to @ContentChild
is not a CSS selector, and you cannot find a content child based on its ID, class or element type. You can only search on the identifier name you gave it using the #
operator.
So given a component called my-comp
and the following usage:
<my-comp><button #buttonName>Click me</button></my_comp>
You can find it using:
@ContentChild('buttonName') button: ElementRef;
Edit
As noted in the OP's comment on ckTag's answer (he beat me to it by a minute), that does mean the calling code will need to know you expect the content to be tagged with a specific name.
If your component does actually need to know detail of its content children, the better answer is actually to provide the directive type to @ContentChild
:
@ContentChild(MyButtonComponent) button: ElementRef;
This is also better, because you can now realistically expect to know the type of content; the calling code can stick #button
on a div
if it feels like it, after all.
That does mean saying goodbye to using a regular HTML button
element, but comes with other benefits. You could, for example, provide a message to guide your calling code, like this:
<ng-content></ng-content>
<div *ngIf="button">Error: Please provide a MyButtonComponent</div>
来源:https://stackoverflow.com/questions/51673978/how-do-i-select-a-contentchild-of-a-native-element-in-angular-6