Joe Joe - 22 days ago 13
Javascript Question

How can I select dynamic elements rendered by *ngIf

As the code provided bellow. I tried to select a dynamic element generated by ngIf but failed.

I used two ways in total.


  1. ElementRef and querySelector



component template:

`<div class="test" *ngIf="expr">
<a id="button">Value 1</a>
</div>
<div class="test" *ngIf="!expr">
<a id="button">Value 2</a>
</div>`


component class:

expr: boolean;

constructor(
private elementRef: ElementRef,
) {
}

ngOnInit(): void{
//Call Ajax and set the value of this.expr based on the callback;
//if expr == true, then show text Value 1;
//if expr == false, then show text Value 2;
}
ngAfterViewInit(): void{
console.log(this.elementRef.nativeElement.querySelector('#button'));
}


The output result is
null
.


  1. @ViewChild



component template:

`<div class="test" *ngIf="expr">
<a #button>Value 1</a>
</div>
<div class="test" *ngIf="!expr">
<a #button>Value 2</a>
</div>`


component class:

@ViewChild('button') button: elementRef;

expr: boolean;

ngOnInit(): void{
//Call Ajax and set the value of this.expr based on the callback;
//if expr == true, then show text Value 1;
//if expr == false, then show text Value 2;
}

ngAfterViewInit(): void{
console.log(this.button);
}


The out put result is
undefined
;

Is there a way to get dynamic dom generated by *ngIf?




Finally the problem has been solved through @ViewChildren.

And to log the updated result, it is necessary to use a separate function.

For example:

Wrong Code:

@ViewChildren('button') buttons: ElementRef;

function(): void{
this.expr = true; // Change expression then the DOM will be changed;
console.log(this.buttons.toArray()); // This is wrong because you will still get the old result;
}


Right Code:

@ViewChildren('button') buttons: ElementRef;

function(): void{
this.expr = true; // Change expression then the DOM will be changed;
}
ngAfterViewInit(): void{
this.buttons.changes.subscribe( e => console.log(this.buttons.toArray()) ); // This is right and you will get the latest result;
}

Answer

You can't get the element when the *ngIf="expr" expression is false because then the element doesn't exist.

The value is not yet set in ngOnInit(), only when ngAfterViewInit() is called.

Plunker example

@Component({
  selector: 'my-app',
  template: `
    <div class="test" *ngIf="prop">
      <a #button id="button1">button1</a>
    </div>
    <div class="test" *ngIf="!boolean">
      <a id="button2">button2</a>
    </div>`
 ,
})
export class App {
  @ViewChild('button') button: ElementRef;

  prop:boolean = true;

  ngAfterViewInit() {
    console.log(this.button);
  }
}

Plunker example with ViewChildren

@Component({
  selector: 'my-app',
  template: `
    <button (click)="prop = !prop">toggle</button>
    <div class="test" *ngIf="prop">
      <a #button id="button1">button1</a>
    </div>
    <div class="test" *ngIf="!boolean">
      <a #button id="button2">button2</a>
    </div>`
 ,
})
export class App {
  @ViewChildren('button') button: QueryList<ElementRef>;

  prop:boolean = true;

  ngAfterViewInit() {
    console.log(this.button.toArray());
    this.button.changes.subscribe(val => {
      console.log(this.button.toArray());
    });

  }
}
Comments