Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parse errors: Reference "#XXX" is defined several times in angular

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?

like image 925
niaomingjian Avatar asked Apr 10 '26 10:04

niaomingjian


1 Answers

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

like image 64
yurzui Avatar answered Apr 12 '26 00:04

yurzui



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!