gar*_*hdn 410 angular-ng-if ngfor angular
我在尝试使用Angular *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);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道简单的解决方案是*ngIf向上移动一个级别但是对于像a循环列表项的情况一样ul,li如果集合为空,我最终将为空,或者我的lis包装在冗余容器元素中.
这个plnkr的例子.
请注意控制台错误:
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]
Run Code Online (Sandbox Code Playgroud)
我做错了什么或这是一个错误?
Gün*_*uer 611
Angular v2不支持同一元素上的多个结构指令.
作为一种解决方法,使用<ng-container>允许您为每个结构指令使用单独元素的元素,但不会将其标记为DOM.
<ng-container *ngIf="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</ng-container>
Run Code Online (Sandbox Code Playgroud)
<ng-template>(<template>在Angular v4之前)允许执行相同但具有不同语法的混淆且不再推荐的语法
<ng-template [ngIf]="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</ng-template>
Run Code Online (Sandbox Code Playgroud)
ima*_*era 58
正如大家所指出的那样,即使在单个元素中有多个模板指令也能在角度1.x中工作,但在Angular 2中不允许这样做.你可以从这里找到更多信息:https://github.com/angular/angular/issues/ 7315
解决方案是使用<template>占位符,所以代码就像这样
<template *ngFor="let nav_link of defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</template>
Run Code Online (Sandbox Code Playgroud)
但由于某种原因,上述情况不起作用,2.0.0-rc.4你可以使用它
<template ngFor let-nav_link [ngForOf]="defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</template>
Run Code Online (Sandbox Code Playgroud)
随着更新,现在2018年角度v6建议使用<ng-container>而不是<template>
所以这是更新的答案.
<ng-container *ngFor="let nav_link of defaultLinks" >
<li *ngIf="nav_link.visible">
.....
</li>
</ng-container>
Run Code Online (Sandbox Code Playgroud)
Ajm*_*sha 41
我还有一个解决方案.
用[hidden]而不是 *ngIf
<div [hidden]="!show" *ngFor="let thing of stuff">
Run Code Online (Sandbox Code Playgroud)
区别在于*ngIf将从DOM中删除元素,而[hidden]实际上CSS通过设置display:none来播放样式
Mar*_*cok 29
正如@Zyzle所提到的,@Günter在评论中提到(https://github.com/angular/angular/issues/7315),这是不受支持的.
同
<ul *ngIf="show">
<li *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
<li>列表为空时没有空元素.甚至<ul>元素也不存在(如预期的那样).
填充列表时,没有冗余容器元素.
@Zyzle在他的评论中提到的github讨论(4792)也提出了另一个使用的解决方案<template>(下面我使用你的原始标记 - 使用<div>s):
<template [ngIf]="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</template>
Run Code Online (Sandbox Code Playgroud)
此解决方案也不会引入任何额外/冗余容器元素.
小智 11
我用这个解决了我的问题
<ng-container *ngFor="let item of menuItems">
<li *ngIf="canShowItem(item)"></li>
</ng-container>
Run Code Online (Sandbox Code Playgroud)
在 html 中:
<div [ngClass]="{'disabled-field': !show}" *ngFor="let thing of stuff">
{{thing.name}}
</div>
Run Code Online (Sandbox Code Playgroud)
在 CSS 中:
.disabled-field {
pointer-events: none;
display: none;
}
Run Code Online (Sandbox Code Playgroud)
这将起作用,但该元素仍将在 DOM 中。
.hidden {
display: none;
}
Run Code Online (Sandbox Code Playgroud)
<div [class.hidden]="!show" *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)
您不能在同一元素上使用ngFor和ngIf。您可以做的是推迟填充正在使用的阵列,ngFor直到单击示例中的切换按钮为止。
这是您可以执行的基本(不太好)方法:http : //plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P
您不能Structural Directive在Angular中对同一个元素使用多个元素,这会造成混乱和结构混乱,因此您需要将它们应用于2个单独的嵌套元素中(或者可以使用ng-container),请从Angular团队阅读以下声明:
每个主机元素一个结构指令
总有一天,您只想在满足特定条件时才重复HTML块。您将尝试将* ngFor和* ngIf放在同一宿主元素上。Angular不会让你。您只能对一个元素应用一个结构指令。
原因是简单。结构化指令可以对宿主元素及其后代进行复杂的处理。当两个指令对同一宿主元素提出要求时,哪个优先?NgIf或NgFor应该先走?NgIf是否可以取消NgFor的效果?如果是这样(看起来应该是这样),Angular应该如何概括取消其他结构性指令的能力?
这些问题没有简单的答案。禁止多个结构性指令使它们无济于事。对于这种用例有一个简单的解决方案:将* ngIf放在包装* ngFor元素的容器元素上 。一个或两个元素都可以是ng容器,因此您不必引入额外的HTML级别。
因此,ng-container如果您具有类或其他某些属性,则可以使用(Angular4)作为包装器(将从dom中删除)或div或span:
<div class="right" *ngIf="show">
<div *ngFor="let thing of stuff">
{{log(thing)}}
<span>{{thing.name}}</span>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
223138 次 |
| 最近记录: |