I want to use the same name of template reference variables for querying at @ViewChildren.
Metadata Properties:
selector - the directive type or the name used for querying.
read - read a different token from the queried elements.
But, I got a template parse error:
Reference "#abc" is defined several times
Sample:
import {AfterViewInit, Component, Directive, Input, QueryList, ViewChildren, ElementRef} from '@angular/core';
@Directive({selector: 'pane'})
export class Pane {
@Input() id: string;
}
@Directive({selector: 'pane1'})
export class Pane1 {
@Input() id: string;
}
@Component({
selector: 'app-root',
template: `
<span #abc id="1"></span>
<pane1 #abc id="2"></pane1>
<pane #abc id="3" *ngIf="shouldShow"></pane>
<button (click)="show()">Show 3</button>
<button (click)="hide()">Hide 3</button>
<div>panes: {{serializedPanes}}</div>
`,
})
export class ViewChildrenComp implements AfterViewInit {
@ViewChildren('abc') panes: QueryList<ElementRef>;
serializedPanes: string = '';
shouldShow = false;
show() { this.shouldShow = true; }
hide() { this.shouldShow = false; }
ngAfterViewInit() {
this.calculateSerializedPanes();
this.panes.changes.subscribe(
(r) => {
this.calculateSerializedPanes();
});
}
calculateSerializedPanes() {
setTimeout(
() => {
this.serializedPanes = this.panes.map(p => p.nativeElement.id).join(', ');
}, 0);
}
}
Question:
1. Whether I can define template reference variables with same name in template?
2. How to query multiple elements using the same selector, not defining names individually?
You can't define template reference variables with the same name in one template.
You can only define it in different templates including EmbeddedViewTemplate, i.e.
<div #abc>
<ng-template #abc>
<ng-template>
<div #abc></div>
</ng-template>
</ng-template>
</div>
should work
or
<div #abc>
<ng-template #abc>
<div #abc></div>
</ng-template>
<ng-template #abc>
<div #abc></div>
</ng-template>
</div>
should also work
How to query multiple elements using the same selector, not defining names individually?
You can define directive like
@Directive({selector: '[id]'})
export class Abc {
constructor(public elRef: ElementRef) {}
}
Selector can be [abc] then you need to add abc attribute to all elements
<span abc id="1"></span>
<pane1 abc id="2"></pane1>
<pane abc id="3" *ngIf="shouldShow"></pane>
But since you have already defined id i use it as selector
After that you can use Abc directive mentioned above as selector for @ViewChildren
@ViewChildren(Abc) panes: QueryList<ElementRef>;
this.serializedPanes = this.panes.map(p => p.elRef.nativeElement.id).join(', ');
Plunker Example
But there is some trick that can help us to have one variable several times. Just wrap your elements into another element i.e.
<div>
<span #abc id="1"></span>
<pane1 #abc id="2"></pane1>
<pane #abc id="3" *ngIf="shouldShow"></pane>
</div>
or
<ng-container>
<span #abc id="1"></span>
<pane1 #abc id="2"></pane1>
<pane #abc id="3" *ngIf="shouldShow"></pane>
</ng-container>
Plunker Example
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