我试图在同一元素上使用Angular qazxsw poi和qazxsw poi时遇到问题。
当试图遍历*ngFor
中的集合时,该集合被视为*ngIf
,因此在尝试访问模板中的属性时失败。
*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);
}
}
中的循环列表项一样的情况,如果集合为空,我最终会得到一个空的*ngIf
,或者我的ul
s包含在冗余的容器元素中。
这个li
的例子。
请注意控制台错误:
li
我做错了什么或这是一个错误?
Angular v2不支持同一元素上的多个结构指令。 作为一种解决方法,使用plnkr元素,它允许您为每个结构指令使用单独的元素,但它不会标记到DOM。
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]
<ng-container>
(Angular v4之前的<ng-container *ngIf="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</ng-container>
)允许执行相同的操作,但语法不同,令人困惑,不再推荐
<ng-template>
现在从angular2 beta 8我们可以在相同的组件<div [ngClass]="{'disabled-field': !show}" *ngFor="let thing of stuff">
{{thing.name}}
</div>
上使用.disabled-field {
pointer-events: none;
display: none;
}
和*ngIf
。
备用:
有时我们不能在*ngFor
,see here(tr
)或th
(table
)中使用HTML标签。我们不能使用另一个HTML标签,但我们必须在相同的情况下执行某些操作,因此我们可以通过这种方式使用HTML5功能标记li
。
ul
<template>
有关angular2 <template ngFor #abc [ngForOf]="someArray">
code here....
</template>
中结构指令的更多信息。
<template [ngIf]="show">
code here....
</template>
您还可以使用see here(而不是模板。请参阅使用模板标记的注释说明),以便在同一HTML元素上同时应用* ngFor和ngIf。下面是一个示例,您可以将* ngIf和* ngFor用于角度表中的相同tr元素。
<div *ngFor="let thing of show ? stuff : []">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
哪里有ng-template
。
注意:
使用<tr *ngFor = "let fruit of fruiArray">
<ng-template [ngIf] = "fruit=='apple'>
<td> I love apples!</td>
</ng-template>
</tr>
标签而不是fruiArray = ['apple', 'banana', 'mango', 'pineapple']
标签的警告是它在某些地方抛出template
。
ng-template
您不能在同一元素上使用多个结构指令。将您的元素包裹在StaticInjectionError
中并在那里使用一个结构指令
正如大家所指出的那样,尽管在单个元素中有多个模板指令在角度1.x中工作,但在Angular 2中不允许这样做。您可以从这里找到更多信息:<template>
解决方案是使用<ng-template [ngIf]="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</ng-template>
作为占位符,因此代码就是这样的
https://github.com/angular/angular/issues/7315
但由于某些原因,上述情况在<template>
不起作用,在这种情况下你可以使用它
<template *ngFor="let nav_link of defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</template>
随着更新,现在2018年角v6推荐使用2.0.0-rc.4
而不是<template ngFor let-nav_link [ngForOf]="defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</template>
所以这是更新的答案。
<ng-container>
我还有一个解决方案。
使用<template>
而不是<ng-container *ngFor="let nav_link of defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</ng-container>
[hidden]
区别在于*ngIf
将从DOM中删除元素,而<div [hidden]="!show" *ngFor="let thing of stuff">
实际上通过设置display:none来播放*ngIf
样式
正如@Zyzle所提到的,@Günter在评论中提到([hidden]
),这是不受支持的。
同
CSS
当列表为空时,没有空的https://github.com/angular/angular/issues/7315元素。甚至<ul *ngIf="show">
<li *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</li>
</ul>
元素也不存在(如预期的那样)。
填充列表时,没有冗余容器元素。
@Zyzle在评论中提到的<li>
也提出了使用<ul>
的另一种解决方案(下面我使用你的原始标记和破折号;使用github discussion (4792)s):
<template>
此解决方案也不会引入任何额外/冗余容器元素。
你不能在同一元素上有<div>
和<template [ngIf]="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</template>
。您可以做的是暂停填充您在ngFor
中使用的数组,直到单击示例中的切换。
这是你可以做到的基本(不太好)的方式:ngIf
下表仅列出设置了“初学者”值的项目。需要.hidden{
display: none;
}
和<div [class.hidden]="!show" *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
来防止html中不需要的行。
最初在相同的*ngFor
标签上有*ngIf
和*ngIf
,但不起作用。为*ngFor
循环添加了<tr>
并将<div>
放在*ngFor
标签中,按预期工作。
*ngIf
你不能在同一个元素上使用Angular中的多个<tr>
,它会产生一个糟糕的混淆和结构,所以你需要在两个独立的嵌套元素中应用它们(或者你可以使用<table class="table lessons-list card card-strong ">
<tbody>
<div *ngFor="let lesson of lessons" >
<tr *ngIf="lesson.isBeginner">
<!-- next line doesn't work -->
<!-- <tr *ngFor="let lesson of lessons" *ngIf="lesson.isBeginner"> -->
<td class="lesson-title">{{lesson.description}}</td>
<td class="duration">
<i class="fa fa-clock-o"></i>
<span>{{lesson.duration}}</span>
</td>
</tr>
</div>
</tbody>
</table>
),从Angular团队阅读这个声明:
每个主机元素一个结构指令
有一天你会想要重复一段HTML,但只有在特定条件成立时才会这样。您将尝试将* ngFor和* ngIf放在同一主机元素上。 Angular不会让你。您可以只对元素应用一个结构指令。
原因很简单。结构指令可以与宿主元素及其后代做复杂的事情。当两个指令声称属于同一个主机元素时,哪一个优先?哪个应该先行,NgIf还是NgFor? NgIf可以取消NgFor的效果吗?如果是这样(似乎应该如此),Angular应如何概括取消其他结构指令的能力?
这些问题没有简单的答案。禁止多个结构指令使它们没有实际意义。这个用例有一个简单的解决方案:将* ngIf放在包装* ngFor元素的容器元素上。一个或两个元素可以是ng-container,因此您不必引入额外的HTML级别。
因此,如果你有类或其他一些属性,你可以使用Structural Directive
(Angular4)作为包装器(将从dom中删除)或div或span:
ng-container
在HTML中:
ng-container
在css中:
<div class="right" *ngIf="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</div>