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


473

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

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


stackoverflow.com/questions/40529537/… ng-container와 함께 갈 것입니다
로버트 킹

답변:


680

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>

5
고마워 놀랍게도 여전히 문서화되어 있지 않습니다 : github.com/angular/angular.io/issues/2303
Alex Fuentes

7
* ngFor 안에 * ngIf가 있어야 할 때 코드는 어떻게 생겼습니까? 즉, IF 조건은 루프 요소의 값을 기반으로합니다.
Yuvraj Patil

22
그냥 넣어 ngFor상기 <ng-container>요소와 ngIf상기 <div>. 또한 두 개의 중첩 <ng-container>랩핑을 가질 수 있습니다 <div>. <ng-container>DOM에 추가되지 않는 도우미 요소 일뿐입니다.
Günter Zöchbauer 2012 년

3
을 사용하는 것이 좋습니다 <ng-container>. <template>구조적 지시문에 "일반"구문을 사용할 수 는 있지만 동일하게 동작합니다 .
Günter Zöchbauer

2
문서에 "호스트 요소 당 하나의 구조적 지시어": "이 사용 사례에 대한 쉬운 해결책이 있습니다. * ngFor 요소를 감싸는 컨테이너 요소에 * ngIf를 넣으십시오." -방금 반복
heringer

71

단일 요소에 여러 템플릿 지시문이 있지만 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>

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>

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

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


1
왜 이것이 대답이 아닌지 잘 모르겠습니다. <template>출력에 표시되지 않는 부모 요소를 추가하는 방법입니다.
Evan Plaice

8

html로 :

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

CSS에서 :

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

5

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

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


왜 둘 다 가질 수 없습니까? 정교한 제발
maurycy

1
그 주위에 토론이 여기에있다 github.com/angular/angular/issues/4792
Zyzle

1
왜 그런 일이 일어나는지 알고 있습니다. 답변의 품질을 향상시키는 you can't것입니다. 일반적으로 좋은 대답은 아니라고 동의합니까?
maurycy

물론, 템플릿에 특정 순서로 배치한다고해서 동일한 순서로 실행될 것이라는 보장은 없기 때문에 함께 사용해서는 안됩니다. 그러나 이것은 'null의'name '속성을 읽을 수 없습니다'가 발생했을 때 정확히 무슨 일이 일어나는지 설명하지 않습니다.
Estus Flask

* ngFor 및 * ngIf (별표 포함)는 구조적 지시문이며 <template> 태그를 생성합니다. ngIf와 같은 구조적 지시문은 HTML 5 템플릿 태그를 사용하여 마법을 수행합니다.
Pardeep Jain

5

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>

4

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

.hidden {
    display: none;
}

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

이것은 <select> <option> 조합에 대한 매우 쉬운 해킹입니다. 간단히 전체 목록 대신 필터링 된 항목을 표시하려고합니다.
davyzhang

대단히 감사합니다!
Abhishek Sharma

3

아래 표에는 "초보자"값이 설정된 항목 만 나열되어 있습니다. 모두 필요 *ngFor와는 *ngIfHTML에서 불필요한 행을 방지 할 수 있습니다.

원래했다 *ngIf*ngFor같은에서 <tr>태그,하지만 작동하지 않습니다. <div>for *ngFor루프를 추가 *ngIf하고 <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>

1
나는 <div>테이블 내부가 거위 아이디어 라고 생각하지 않습니다 . 특히 더 나은 대안이있을 때. IE의 요소가 특히 까다로운 IE에서 작동하는지 확인 했습니까?<table>
Günter Zöchbauer

3

angular2 베타 8로 업데이트

이제 angular2 베타 우리가 사용할 수있는 8에서로 *ngIf*ngFor같은 구성 요소에는 여기를 참조하십시오 .

번갈아 하는:

때때로 우리가 같은 다른 내부 HTML 태그를 사용할 수 없습니다 tr, th( table) 또는 li( ul). 다른 HTML 태그를 사용할 수 없지만 같은 상황에서 몇 가지 작업을 수행해야 HTML5 기능 태그를 사용할 수 있습니다<template> 이러한 방식으로 를 .

ng 템플릿을 사용하는 경우 :

<template ngFor #abc [ngForOf]="someArray">
    code here....
</template>

ng 템플릿을 사용하는 경우 :

<template [ngIf]="show">
    code here....
</template>    

angular2의 구조적 지시문에 대한 자세한 내용 은 여기를 참조하십시오 .


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

1

동일한 HTML 요소에 * ngForngIfng-template모두 적용하기 위해 템플릿 대신 사용할 수 있습니다 (템플릿 태그 사용에 대한 참고 사항 참조) . 다음은 각도 테이블에서 동일한 tr 요소에 * ngIf 및 * ngFor모두 사용할 수있는 예 입니다.

<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특정 위치에 발생 한다는 것 입니다.


0

<!-- Since angular2 stable release multiple directives are not supported on a single element(from the docs) still you can use it like below -->


<ul class="list-group">
                <template ngFor let-item [ngForOf]="stuff" [ngForTrackBy]="trackBy_stuff">
                    <li *ngIf="item.name" class="list-group-item">{{item.name}}</li>
                </template>
   </ul>


li 항목은 이름이있는 경우에만 표시됩니다.
Rajiv

3
이 답변이 여기에 어떻게 가치를 더합니까? 이미 다른 답변에서 제공하지 않은 것을 제공하지 않거나 무언가를 놓쳤습니까?
Günter Zöchbauer

0

동일한 요소에 여러 구조적 지시문을 사용할 수 없습니다. 요소를 감싸고 ng-template하나의 구조적 지시문을 사용 하십시오.


0

배열 길이를 확인하여 다른 방법 으로이 작업을 수행 할 수 있습니다

<div *ngIf="stuff.length>0">
  <div *ngFor="let thing of stuff">
    {{log(thing)}}
    <span>{{thing.name}}</span>
  </div>
</div>

-1

app.component.ts

import {NgModule, Component} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';

@Component({
  selector: 'ngif-example',
  template: `
<h4>NgIf</h4>
<ul *ngFor="let person of people">
  <li *ngIf="person.age < 30"> (1)
  {{ person.name }} ({{ person.age }})
  </li>
</ul>
`
})
class NgIfExampleComponent {

  people: any[] = [
    {
      "name": "yogesh ",
      "age": 35
    },
    {
      "name": "gamesh",
      "age": 32
    },
    {
      "name": " Meyers",
      "age": 21
    },
    {
      "name": " Ellis",
      "age": 34
    },
    {
      "name": " Tyson",
      "age": 32
    }
  ];
}

app.component.html

<ul *ngFor="let person of people" *ngIf="person.age < 30">
  <li>{{ person.name }}</li>
</ul>

산출

Meyers(21)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.