Consider the following template:
<my-component #ref></my-component>
<my-comp-2 [maxWidth]="ref.clientWidth"></my-comp-2>
My component doesn't have a .clientWidth
property on it, but the element itself that hosts my component does.
Is there a name I could use or some other similar solution for getting a reference to the element itself in the HTML alone? For instance, I would like to do something like this:
<my-component #ref="element"></my-component>
The problem is that there is no directive with the exportAs
option named "element". Nor is there any built-in equivalent documented on the Angular site.
I am aware that I could add clientWidth
as a property, and that I could get a reference to the element within <my-component>
class via ElementRef<HTMLElement>
and dependency injection, but I would like a solution that involves HTML alone. Does such a solution exist?
I feel that your answer is the correct, but as curiosity , you can make a hard-work-around: create a directive like
@Directive({
selector: '[element-directive]',
exportAs: 'ngDirective',
})
export class MyDirective {
constructor(public elementRef: ElementRef){}
}
And use
<my-component element-directive #ref="ngDirective">
</my-component>
<my-comp-2 [style.max-width]="ref.elementRef.nativeElement.offsetWidth+'px'">
</my-comp-2>
The other way, as you indicate, is in constructor of my-component, inject ElementRef and make it public
constructor(public elementRef:ElementRef){}
Then, you can use
<my-comp-2 [style.max-width]="ref.elementRef.nativeElement.offsetWidth+'px'">
</my-comp-2>
Or you can create any function in my-component that return what do you want and call this function
NOTE: I use style.max-width, I don't know if your my-comp2 has an input or not
The DirectiveBinder
class in the Angular compiler package appears to treat any non-named template reference as a reference to the component (if it is one) or the element (if it's not).
The relevant code is here:
node.references.forEach(ref => {
let dirTarget: DirectiveT|null = null;
// If the reference expression is empty, then it matches the "primary" directive on the node
// (if there is one). Otherwise it matches the host node itself (either an element or
// <ng-template> node).
if (ref.value.trim() === '') {
// This could be a reference to a component if there is one.
dirTarget = directives.find(dir => dir.isComponent) || null;
} else {
// This should be a reference to a directive exported via exportAs.
dirTarget =
directives.find(
dir => dir.exportAs !== null && dir.exportAs.some(value => value === ref.value)) ||
null;
// Check if a matching directive was found.
if (dirTarget === null) {
// No matching directive was found - this reference points to an unknown target. Leave it
// unmapped.
return;
}
}
if (dirTarget !== null) {
// This reference points to a directive.
this.references.set(ref, {directive: dirTarget, node});
} else {
// This reference points to the node itself.
this.references.set(ref, node);
}
});
The first if branch is when no name is given (ie #ref
or #ref=""
) and the else loops through any directives on the element being checked. Above this shows that no directives is a possibility, suggesting that there isn't some place where a special built-in "element" directive is being added.
Conclusion 1: If it's a component and there is no name in the template reference variable, then it will always refer to the component.
Conclusion 2: There are no special built-in directives in every case. Exceptions may exist for some standard HTML elements (eg <input>
), but that doesn't help us here.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.