[angular] 동일한 요소에서 * ngIf 및 * ngFor 오류 발생

나는 각도의를 사용하려고 시도에 문제에 봉착 *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);
  }

}

나는 쉬운 솔루션은 이동하는 것입니다 알고 *ngIfA의 목록 항목에 걸쳐 반복과 같은 수준까지하지만 시나리오 ul나도 빈으로 끝낼 것, li컬렉션이 비어있는 경우, 또는 내을li 의 중복 컨테이너 요소에 싸여.

plnkr의 .

콘솔 오류에 유의하십시오.

EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]

내가 잘못하고 있거나 버그입니까?



답변

Angular v2는 동일한 요소에서 둘 이상의 구조적 지시문을 지원하지 않습니다.
해결 방법 <ng-container>으로 각 구조적 지시문에 대해 별도의 요소를 사용할 수 있는 요소를 사용하지만 DOM에 찍히지 않습니다 .

<ng-container *ngIf="show">
  <div *ngFor="let thing of stuff">
    {{log(thing)}}
    <span>{{thing.name}}</span>
  </div>
</ng-container>

<ng-template>( <template>Angular v4 이전)는 혼란스럽고 더 이상 권장되지 않는 다른 구문으로 동일하게 수행 할 수 있습니다.

<ng-template [ngIf]="show">
  <div *ngFor="let thing of stuff">
    {{log(thing)}}
    <span>{{thing.name}}</span>
  </div>
</ng-template>


답변

단일 요소에 여러 템플릿 지시문이 있지만 angular 1.x에서는 작동하지만 Angular 2에서는 허용되지 않습니다. https://github.com/angular/angular/issues/ 7315

2016 각도 2 베타

해결책은 <template>자리 표시 자로 사용하는 것이므로 코드는 다음과 같습니다.

<template *ngFor="let nav_link of defaultLinks"  >
   <li *ngIf="nav_link.visible">
       .....
   </li>
</template>

그러나 어떤 이유로 든 위의 2.0.0-rc.4경우에는 작동하지 않습니다.

<template ngFor let-nav_link [ngForOf]="defaultLinks" >
   <li *ngIf="nav_link.visible">
       .....
   </li>
</template>

업데이트 된 답변 2018

업데이트로 2018 년 현재 angular v6 <ng-container>대신에 사용 하는 것이 좋습니다<template>

여기에 업데이트 된 답변이 있습니다.

<ng-container *ngFor="let nav_link of defaultLinks" >
   <li *ngIf="nav_link.visible">
       .....
   </li>
</ng-container>


답변

@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>

<li>목록이 비어 있으면 빈 요소 가 없습니다 . 심지어 <ul>(예상대로) 요소가 존재하지 않습니다.

목록이 채워지면 중복 컨테이너 요소가 없습니다.

GitHub의 토론 (4792) @Zyzle 그의 주석에서 언급 한 또한 사용하여 다른 솔루션을 제공합니다 <template>– (사용 나는 원래 마크 업을 사용하고 이하 <div>: S)

<template [ngIf]="show">
  <div *ngFor="let thing of stuff">
    {{log(thing)}}
    <span>{{thing.name}}</span>
  </div>
</template>

이 솔루션에는 여분 / 중복 컨테이너 요소도 도입되지 않습니다.


답변

html로 :

<div [ngClass]="{'disabled-field': !show}" *ngFor="let thing of stuff">
    {{thing.name}}
</div>

CSS에서 :

.disabled-field {
    pointer-events: none;
    display: none;
}


답변

당신은 할 수 없습니다 ngForngIf같은 요소. 할 수있는 일은 ngFor예제의 토글을 클릭 할 때까지 사용중인 배열을 채우는 것 입니다.

기본적인 방법은 다음과 같습니다. http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P


답변

Structural Directive같은 요소에 Angular에서 둘 이상을 사용할 수 없으므로 혼동과 구조가 잘못되므로 두 개의 별도 중첩 요소에 적용해야합니다 (또는 사용할 수 있음 ng-container). Angular 팀 에서이 문장을 읽으십시오.

호스트 요소 당 하나의 구조적 지시어

언젠가는 특정 조건이 참일 때만 HTML 블록을 반복하고 싶을 것입니다. 당신은 둘 다 넣어하려고합니다 * ngFor* ngIf을 동일한 호스트 요소. 각도는 당신을 못하게합니다. 하나의 구조 지시문 만 요소에 적용 할 수 있습니다.

그 이유는 단순성입니다. 구조적 지시어는 호스트 요소와 그 하위 요소로 복잡한 작업을 수행 할 수 있습니다. 두 개의 지시문이 동일한 호스트 요소에 대한 소유권을 주장 할 때 어느 지시어가 우선합니까? 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>


답변

이것은 작동하지만 요소는 여전히 DOM에 있습니다.

.hidden {
    display: none;
}

<div [class.hidden]="!show" *ngFor="let thing of stuff">
    {{log(thing)}}
    <span>{{thing.name}}</span>
</div>