正如下面提供的代码。我试图选择由ngIf生成的动态元素,但失败了。
我总共使用了两种方式。
组件模板:
`<div class="test" *ngIf="expr">
<a id="button">Value 1</a>
</div>
<div class="test" *ngIf="!expr">
<a id="button">Value 2</a>
</div>`
组件类:
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'));
}
输出结果为null
。
组件模板:
`<div class="test" *ngIf="expr">
<a #button>Value 1</a>
</div>
<div class="test" *ngIf="!expr">
<a #button>Value 2</a>
</div>`
组件类:
@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);
}
输出结果为undefined
;
有没有办法让* ngIf生成动态dom?
最后,问题已经通过@ViewChildren解决了。
要记录更新的结果,必须使用单独的功能。
例如:
错误的代码:
@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;
}
正确的代码:
@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;
}
答案 0 :(得分:3)
当*ngIf="expr"
表达式为false时,您无法获取该元素,因为该元素不存在。
仅当ngOnInit()
被调用时,该值才在ngAfterViewInit()
中设置。
@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());
});
}
}
答案 1 :(得分:2)
如果您仅在某人与其互动时(例如点击它)或与其中的兄弟元素或子元素一起使用该元素,您可以将该元素与该事件一起传递。
模板:
<div class="test" *ngIf="expr">
<a #b id="button1" (click)="onButton1(b)">button1</a>
</div>
代码:
onButton1(button: HTMLButtonElement) {
}
如果您需要不与其互动的元素,您还可以查看ViewChildren
查询而不是ViewChild
。
您可以使用
进行设置@ViewChildren('button') buttons: QueryList<ElementRef>;
然后,您可以通过this.buttons.changes.subscribe(...)
订阅与选择器匹配的元素的更改。如果创建或删除元素,您将通过订阅收到通知。然而,我的第一种方式涉及更少的样板代码。
另外,您也可以在确定元素存在的时刻(通过一些前提条件)同步访问QueryList
。在您的示例中,您应该能够使用
let button: ElementRef = this.buttons.first;
在这些情况下。
答案 2 :(得分:0)
<div class="test" *ngIf="boolean">
<a #button id="button1">button1</a>
</div>
@ViewChild('button') button: elementRef;
console.log(this.button);
ID =&#39;按钮1&#39;,不是&#39;按钮&#39;?
var target = document.getElementById('Button1');
答案 3 :(得分:0)
这并不是最好的,但是我使用[ngClass]代替了类似的情况* ngIf。 只需使用“ display:none”创建一个类,并在需要时隐藏元素。可以毫无问题地访问使用@ViewChild选择的元素。 现在,您可以在搜索更好的解决方案或更优雅的解决方案时使用这个小的“ hack”。 例如。
.hide-element{
display: none;
}
<div class="test" [ngClass]="expr === 'yourTest' ? 'hide-element' : null">
<a #b id="button1" (click)="onButton1(b)">button1</a>
</div>
如果您要处理一些异步返回,则可以使用异步管道
<div class="test" [ngClass]="(expr | async) === 'yourTest' ? 'hide-element' : null">
<a #b id="button1" (click)="onButton1(b)">button1</a>
</div>
希望有帮助。