本文翻译自:*ngIf and *ngFor on same element causing error
I'm having a problem with trying to use Angular's *ngFor
and *ngIf
on the same element. 我在尝试在同一元素上使用Angular的*ngFor
和*ngIf
问题。
When trying to loop through the collection in the *ngFor
, the collection is seen as null
and consequently fails when trying to access its properties in the template. 当尝试遍历*ngFor
中的集合时,该集合被视为null
,因此在尝试访问其模板中的属性时失败。
@Component({
selector: 'shell',
template: `
<h3>Shell</h3><button (click)="toggle()">Toggle!</button>
<div *ngIf="show" *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
`
})
export class ShellComponent implements OnInit {
public stuff:any[] = [];
public show:boolean = false;
constructor() {}
ngOnInit() {
this.stuff = [
{ name: 'abc', id: 1 },
{ name: 'huo', id: 2 },
{ name: 'bar', id: 3 },
{ name: 'foo', id: 4 },
{ name: 'thing', id: 5 },
{ name: 'other', id: 6 },
]
}
toggle() {
this.show = !this.show;
}
log(thing) {
console.log(thing);
}
}
I know the easy solution is to move the *ngIf
up a level but for scenarios like looping over list items in a ul
, I'd end up with either an empty li
if the collection is empty, or my li
s wrapped in redundant container elements. 我知道简单的解决方案是将*ngIf
提升到一个级别,但是对于诸如循环遍历ul
列表项之类的方案,如果集合为空,我最终将得到一个空li
,或者将我的li
包裹在冗余容器中元素。
Example at this plnkr . 此plnkr的示例 。
Note the console error: 注意控制台错误:
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]
Am I doing something wrong or is this a bug? 我是在做错什么还是错误?
#1楼
参考:https://stackoom.com/question/2LQ57/ngIf和-ngFor在同一元素上导致错误
#2楼
You can't have ngFor
and ngIf
on the same element. 您不能在同一元素上使用ngFor
和ngIf
。 What you could do is hold off on populating the array you're using in ngFor
until the toggle in your example is clicked. 您可以做的就是推迟填充您在ngFor
使用的数组,直到单击示例中的切换开关为止。
Here's a basic (not great) way you could do it: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P 这是您可以执行的基本(不太好)方法: http : //plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P
#3楼
As @Zyzle mentioned, and @Günter mentioned in a comment ( https://github.com/angular/angular/issues/7315 ), this is not supported. 正如@Zyzle提到的和@Günter在评论中提到的( https://github.com/angular/angular/issues/7315 ),不支持此功能。
With 用
<ul *ngIf="show">
<li *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</li>
</ul>
there are no empty <li>
elements when the list is empty. 当列表为空时,没有空的<li>
元素。 Even the <ul>
element does not exist (as expected). 甚至<ul>
元素也不存在(按预期)。
When the list is populated, there are no redundant container elements. 填充列表后,将没有多余的容器元素。
The github discussion (4792) that @Zyzle mentioned in his comment also presents another solution using <template>
(below I'm using your original markup ‐ using <div>
s): @Zyzle在他的评论中提到的github讨论(4792)也提出了使用<template>
另一种解决方案(在下面,我使用的是原始的标记-using <div>
):
<template [ngIf]="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</template>
This solution also does not introduce any extra/redundant container elements. 此解决方案也不会引入任何多余/冗余的容器元素。
#4楼
Updated to angular2 beta 8 更新到angular2 beta 8
Now as from angular2 beta 8 we can use *ngIf
and *ngFor
on same component see here . 现在从angular2 beta 8开始,我们可以在同一组件上使用*ngIf
和*ngFor
, 请参见此处 。
Alternate: 备用:
Sometimes we can't use HTML tags inside another like in tr
, th
( table
) or in li
( ul
). 有时我们不能在另一个内部使用HTML标记,例如tr
, th
( table
)或li
( ul
)。 We cannot use another HTML tag but we have to perform some action in same situation so we can HTML5 feature tag <template>
in this way. 我们不能使用其他HTML标记,但必须在相同情况下执行某些操作,因此我们可以以这种方式使用HTML5功能标记<template>
。
ngFor using template: ng对于使用模板:
<template ngFor #abc [ngForOf]="someArray">
code here....
</template>
ngIf using template: ng如果使用模板:
<template [ngIf]="show">
code here....
</template>
For more information about structural directives in angular2 see here . 有关angular2中的结构指令的更多信息, 请参见此处 。
#5楼
As everyone pointed out even though having multiple template directives in a single element works in angular 1.x it is not allowed in Angular 2. you can find more info from here : https://github.com/angular/angular/issues/7315 每个人都指出,即使单个元素中包含多个模板指令也可以在angular 1.x中使用,但在Angular 2中是不允许的。您可以在此处找到更多信息: https : //github.com/angular/angular/issues/ 7315
2016 angular 2 beta 2016角2 Beta
solution is to use the <template>
as a placeholder, so the code goes like this 解决方案是使用<template>
作为占位符,因此代码如下所示
<template *ngFor="let nav_link of defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</template>
but for some reason above does not work in 2.0.0-rc.4
in that case you can use this 但是由于上述原因,在这种情况下您无法使用2.0.0-rc.4
<template ngFor let-nav_link [ngForOf]="defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</template>
Updated Answer 2018 更新的答案2018
With updates, right now in 2018 angular v6 recommend to use <ng-container>
instead of <template>
有了更新,Angular v6现在建议在2018年使用<ng-container>
代替<template>
so here is the updated answer. 所以这是更新的答案。
<ng-container *ngFor="let nav_link of defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</ng-container>
#6楼
This will work but the element will still in the DOM. 这将起作用,但是元素仍将在DOM中。
.hidden{
display: none;
}
<div [class.hidden]="!show" *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>