Como obter a referência do elemento no template Angular em vez da referência do componente
Considere o seguinte modelo:
<my-component #ref></my-component>
<my-comp-2 [maxWidth]="ref.clientWidth"></my-comp-2>
Meu componente não tem uma .clientWidthpropriedade, mas o próprio elemento que hospeda meu componente tem.
Existe um nome que eu poderia usar ou alguma outra solução semelhante para obter uma referência para o próprio elemento apenas no HTML? Por exemplo, eu gostaria de fazer algo assim:
<my-component #ref="element"></my-component>
O problema é que não existe uma diretiva com a exportAsopção chamada "elemento". Nem há qualquer equivalente embutido documentado no site Angular.
Estou ciente de que poderia adicionar clientWidthcomo uma propriedade e obter uma referência ao elemento dentro da <my-component>classe por meio de ElementRef<HTMLElement>injeção de dependência, mas gostaria de uma solução que envolvesse apenas HTML. Essa solução existe?
Respostas
Eu sinto que sua resposta está correta, mas como curiosidade , você pode dar um jeito de contornar: crie uma diretriz como
@Directive({
selector: '[element-directive]',
exportAs: 'ngDirective',
})
export class MyDirective {
constructor(public element:ElementRef){}
}
E use
<my-component element-directive #ref="ngDirective">
</my-component>
<my-comp-2 [style.max-width]="ref.elementRef.nativeElement.offsetWidth+'px'">
</my-comp-2>
A outra maneira, como você indicou, é no construtor de my-component, injete ElementRef e torne-o público
constructor(public elementRef:ElementRef){}
Então, você pode usar
<my-comp-2 [style.max-width]="ref.elementRef.nativeElement.offsetWidth+'px'">
</my-comp-2>
Ou você pode criar qualquer função em my-component que retorne o que você quer e chame esta função
NOTA: Eu uso style.max-width, não sei se seu my-comp2 tem uma entrada ou não
A DirectiveBinder classe no pacote do compilador Angular parece tratar qualquer referência de template não nomeada como uma referência ao componente (se for um) ou ao elemento (se não for).
O código relevante está aqui:
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);
}
});
O primeiro if branch é quando nenhum nome é fornecido ( #refou seja, ou #ref="") e o else faz um loop por quaisquer diretivas no elemento que está sendo verificado. Acima isso mostra que nenhuma diretiva é uma possibilidade, sugerindo que não há algum lugar onde uma diretiva de "elemento" embutida especial está sendo adicionada.
Conclusão 1: Se for um componente e não houver nome na variável de referência do template, então sempre fará referência ao componente.
Conclusão 2: Não há diretivas internas especiais em todos os casos. Podem existir exceções para alguns elementos HTML padrão (por exemplo <input>), mas isso não nos ajuda aqui.