How do I select a ContentChild of a native element in Angular 6?

空扰寡人 提交于 2020-02-02 06:08:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!