How can I select dynamic elements created by * ngIf

Like the code below. I tried to select the dynamic element generated by ngIf, but could not.

I used two methods in total.

  • 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 result of the output 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); } 

Output Result: undefined ;

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


Finally, the problem is resolved using @ViewChildren.

And to register an updated result, you must use a separate function.

For instance:

Incorrect 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; } 
+5
source share
3 answers

You cannot get an element if the expression *ngIf="expr" false, because then the element does not exist.

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

Plunger 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()); }); } } 
+3
source

If you need an element only at the moment when someone interacts with it (for example, clicks on it) or with its sibling or child element, you can pass an event link to it.

Template:

 <div class="test" *ngIf="expr"> <a #b id="button1" (click)="onButton1(b)">button1</a> </div> 

code:

 onButton1(button: HTMLButtonElement) { } 

If you need an element without interacting with it, you can also view the ViewChildren request instead of ViewChild .

You can configure it with

 @ViewChildren('button') buttons: QueryList<ElementRef>; 

You can then subscribe to changes to elements that match the selector through this.buttons.changes.subscribe(...) . If an item is created or deleted, you will receive a notification by subscription. However, my first method involves much less boilerplate code.

Alternatively, you can also only access the QueryList synchronously when you are sure that this element exists (through some preconditions). In your example, you can get a button with

 let button: ElementRef = this.buttons.first; 

in these cases.

+2
source
 <div class="test" *ngIf="boolean"> <a #button id="button1">button1</a> </div> @ViewChild('button') button: elementRef; console.log(this.button); 

id = 'button1' and not 'button'?

 var target = document.getElementById('Button1'); 
0
source

Source: https://habr.com/ru/post/1259583/


All Articles