* ngFor를 사용하여 액세스 키 및 오브젝트 값


426

나는 비트가 도착하는 방법에 대해 혼란 스러워요 keyvalue사용하는 동안 angular2에서 객체의 *ngFor객체를 통해 반복합니다. angular 1.x에는 다음과 같은 구문이 있습니다.

ng-repeat="(key, value) in demo"

하지만 angular2에서 동일한 작업을 수행하는 방법을 모르겠습니다. 나는 성공하지 않고 비슷한 것을 시도했다.

<ul>
  <li *ngFor='#key of demo'>{{key}}</li>
</ul>

demo = {
    'key1': [{'key11':'value11'}, {'key12':'value12'}],
    'key2': [{'key21':'value21'}, {'key22':'value22'}],
  }

내 시도와 함께 plnkr이 있습니다 : http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

어떻게 얻을 수 key1key2사용하여 동적으로 *ngFor? 광범위하게 검색 한 후 파이프를 사용한다는 아이디어를 찾았지만 어떻게 해야할지 모르겠습니다. angular2에서 동일한 작업을 수행하기위한 내장 파이프가 있습니까?


2
현재 key, valueangular2 ngFor에는 페어 종류의 구문이 지원되지 않습니다 . 이 답변을
Pankaj Parkar

@PankajParkar 예, 이미이 답변을 읽었습니다. 지금 어떤 대안?
Pardeep Jain

@Pradeep 나는 이것에 대한 다른 방법을 생각하지 않습니다, 당신은 Pipe이것을 위해 자신 을 만들기 위해 가야 합니다 ..
Pankaj Parkar

흠 그러나 나는 같은 파이프를 만드는 법을 모른다.
Pardeep Jain

내가 참고로 당신에게 준 @Pradeep 답변은 그 구현을 가지고 있습니다. 그들은 작동해야합니다.
Pankaj Parkar

답변:


398

Object.keys템플릿에 액세스 할 수 있으며 사용할 *ngFor.

@Component({
  selector: 'app-myview',
  template: `<div *ngFor="let key of objectKeys(items)">{{key + ' : ' + items[key]}}</div>`
})

export class MyComponent {
  objectKeys = Object.keys;
  items = { keyOne: 'value 1', keyTwo: 'value 2', keyThree: 'value 3' };
  constructor(){}
}


25
이것은 더 낫고 더 효율적인 솔루션입니다
Aous1000

1
@tomtastico 3D 배열에 이것을 어떻게 표시 하시겠습니까? 예를 들어 { "1": { "1.1": [ "1.1.1", "1.1.2"]}}입니다. 그런 다음 3 ngFor 's
Frank

@ 프랭크 당신은 방금 직접 말했다. *ngFors를 중첩시킵니다 . 처음 두 개 objectKeys는 가장 내부적으로 필요하지 않습니다 (단지 배열 일뿐이므로).
tomtastico

1
대박. objectKeys = Object.keys 설정은 HTML에서 객체의 길이를 확인할 수있는 가장 간단한 방법입니다.
JAC

393

마찬가지로 각도 (V6.1.0)의 최신 버전 , 각도 팀은 새로 만들기로 명명 같은 위해 파이프에 내장 추가했다 keyvalue에,지도, 객체를 통해 당신에게 반복 처리를하기 위해 파이프와 배열 common각 패키지의 모듈. 예를 들어-

<div *ngFor="let item of testObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

일하는 예

더 유용한 정보는 여기를 확인하십시오-

Angular v5 이하를 사용하거나 파이프를 사용하려면이 답변을 따르십시오.


1
좋은 물건 - - 들으 롤 난 그냥 접속이 파이프 NG6 업데이트를해야했다
danday74

36
사용자 정의 비교기를 사용하여 원래 키 순서를 유지할 수 있으며 *ngFor="let item of testObject | keyvalue:keepOriginalOrder" 클래스에서 다음을 정의하십시오. public keepOriginalOrder = (a, b) => a.key
mike-shtil

2
공개 keepOriginalOrder = (a, b) => a.key thx 이것에 대해 많이
Kumaresan Perumal

1
이것은 답이 될 것입니다-각도 7에서 잘 작동
calios

1
믿을 수없는이 밖에 없었다 첫 번째 버전 이후
카를로스 핀존

227

각 요소에 대한 키 목록을 반환하는 사용자 지정 파이프를 만들 수 있습니다. 그런 것 :

import { PipeTransform, Pipe } from '@angular/core';

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push(key);
    }
    return keys;
  }
}

다음과 같이 사용하십시오.

<tr *ngFor="let c of content">           
  <td *ngFor="let key of c | keys">{{key}}: {{c[key]}}</td>
</tr>

편집하다

키와 값이 모두 포함 된 항목을 반환 할 수도 있습니다.

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push({key: key, value: value[key]});
    }
    return keys;
  }
}

다음과 같이 사용하십시오.

<span *ngFor="let entry of content | keys">           
  Key: {{entry.key}}, value: {{entry.value}}
</span>

1
에서 누락 된 닫는 대괄호주의keys.push({key: key, value: value[key]);
마튼 Pallagi

49
실제로 파이프 안에서 파이프를 사용하여 *ngFor표현 내부에 컬렉션을 만드는 것을 권장하지 않습니다 . 변경 감지기가 변경을 확인할 때마다 콜렉션을 생성해야하기 때문에 성능 병목 현상이 발생합니다.
마틴

3
해결책 주셔서 감사합니다 ... 문제는 객체가 변경 될 때마다 파이프가 업데이트되지 않는다는 것입니다. pure:false파이프에 추가 하면 매우 비효율적입니다. 객체를 변경할 때마다 (항목 제거) 파이프를 수동으로 업데이트 할 수있는 솔루션이 있습니까?
ncohen 2016 년

4
대답은 약간 구식입니다. * ngFor = "# entry of content | keys"행이 제대로 작동하지 않고 for ... in 루프가 "for (const key of object.keys (value))"로 변경하는 것이 좋습니다.
Experimenter

2
@RachChen 템플릿에 없음 : common: NgFor has been removed as it was deprecated since v4. Use NgForOf instead. This does not impact the use of*ngFor in your templates.( jaxenter.com/road-to-angular-5-133253.html )
mwld

49

최신 정보

6.1.0-beta.1 에서는 KeyValuePipehttps://github.com/angular/angular/pull/24319 에 도입되었습니다.

<div *ngFor="let item of {'b': 1, 'a': 1} | keyvalue">
  {{ item.key }} - {{ item.value }}
</div>

플 런커 예

이전 버전

또 다른 방법은 NgForIn다음과 같이 사용될 지시문 을 작성 하는 것입니다.

<div *ngFor="let key in obj">
   <b>{{ key }}</b>: {{ obj[key] }}
</div>

플 런커 예

ngforin.directive.ts

@Directive({
  selector: '[ngFor][ngForIn]'
})
export class NgForIn<T> extends NgForOf<T> implements OnChanges {

  @Input() ngForIn: any;

  ngOnChanges(changes: NgForInChanges): void {
    if (changes.ngForIn) {
      this.ngForOf = Object.keys(this.ngForIn) as Array<any>;

      const change = changes.ngForIn;
      const currentValue = Object.keys(change.currentValue);
      const previousValue = change.previousValue ? Object.keys(change.previousValue) : undefined;
      changes.ngForOf =  new SimpleChange(previousValue, currentValue, change.firstChange);

      super.ngOnChanges(changes);
    }
  }
}

43

Angular 6.1에서 키값 파이프를 사용할 수 있습니다 .

<div *ngFor="let item of testObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

그러나 결과 목록을 키 값으로 정렬하는 것은 불편합니다. 중립적 인 것이 필요한 경우 :

@Pipe({ name: 'keyValueUnsorted', pure: false  })
export class KeyValuePipe implements PipeTransform {
  transform(input: any): any {
    let keys = [];
    for (let key in input) {
      if (input.hasOwnProperty(key)) {
        keys.push({ key: key, value: input[key]});
      }
    }
    return keys;
  }
}

pure : false 파이프 속성 을 지정하는 것을 잊지 마십시오 . 이 경우 입력 참조가 변경되지 않은 경우에도 변경 감지주기마다 파이프가 호출됩니다 (물체에 속성을 추가 할 때도 마찬가지 임).



26

@Thierry의 답변을 예를 들어 설명합니다.

key and value* ngFor 루프에서 가져올 파이프 나 메소드가 없습니다 . 동일한 파이프를 만들어야합니다. thierry가 말했듯이 여기에 코드가있는 대답이 있습니다.

** 파이프 클래스는 입력 값과 선택적 매개 변수 문자열 배열을 사용하여 변환 된 값을 리턴하는 PipeTransform 인터페이스의 변환 메소드를 구현합니다.

** 변환 방법은 파이프에 필수적입니다. PipeTransform 인터페이스는 해당 메소드를 정의하고 툴링 및 컴파일러를 모두 안내합니다. 선택 사항입니다. Angular는 변환 방법을 찾고 상관없이 실행합니다. 자세한 정보는 파이프를 참조하십시오.

import {Component, Pipe, PipeTransform} from 'angular2/core';
import {CORE_DIRECTIVES, NgClass, FORM_DIRECTIVES, Control, ControlGroup, FormBuilder, Validators} from 'angular2/common';

@Component({
    selector: 'my-app',
    templateUrl: 'mytemplate.html',
    directives: [CORE_DIRECTIVES, FORM_DIRECTIVES],
    pipes: [KeysPipe]
})
export class AppComponent { 

  demo = {
    'key1': 'ANGULAR 2',
    'key2': 'Pardeep',
    'key3': 'Jain',
  }
}


@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push({key: key, value: value[key]});
    }
    return keys;
  }
}

HTML 부분은 다음과 같습니다.

<ul>
  <li *ngFor='#key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>

Plnkr 작업 http://plnkr.co/edit/50LlK0k6OnMnkc2kNHM2?p=preview

RC로 업데이트

의견에 user6123723 (thanks)에서 제안한대로 여기 업데이트입니다.

<ul>
  <li *ngFor='let key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>

이것은 업데이트가 필요합니다 : 식 안에 "#"가 표시되는 경고는 더 이상 사용되지 않습니다. 대신 "let"을 사용하십시오! ( "</ li>-> <ul * ngIf ="demo "> <li [ERROR->] * ngFor = '# key of demo | keys'> 키 : {{key.key}}, 값 : { {key.value}} </ li> ") : myComponent @ 56 : 6
user6123723

이것이 새로운 것인지 확실하지 않지만 문서에서 인용하려면> 파이프를 AppModule의 선언 배열에 포함시켜야합니다.
Akzidenzgrotesk

18

@Marton은 파이프가 각 변경 감지에 대해 새로운 컬렉션을 생성한다는 근거로 허용 된 답변 에 대해 중요한 반대 의견을 제시 했습니다. 대신 뷰가 다음과 같이 사용할 수있는 다양한 유틸리티 기능을 제공하는 HtmlService를 만듭니다.

@Component({
  selector: 'app-myview',
  template: `<div *ngFor="let i of html.keys(items)">{{i + ' : ' + items[i]}}</div>`
})
export class MyComponent {
  items = {keyOne: 'value 1', keyTwo: 'value 2', keyThree: 'value 3'};
  constructor(private html: HtmlService){}
}

@Injectable()
export class HtmlService {
  keys(object: {}) {
    return Object.keys(object);
  }
  // ... other useful methods not available inside html, like isObject(), isArray(), findInArray(), and others...
}

2
그리고 Object.keys(...)* ngFor 내부 보다 어떻게 더 좋습니까?
Simon_Weaver

8
던질 것이기 때문에 : TypeError: Cannot read property 'keys' of undefined. 템플릿에서 지원되지 않는 것 같습니다.
Stephen Paul

1
이것은 솔루션으로 매우 잘 작동하며 위에서 지적한 성능 문제를 피합니다. stackoverflow.com/questions/35534959/…
J. Adam 코너

안녕하세요,이 b는 template옵션이 아니라 템플릿의 실제 HTML 코드에서 사용할 수 있습니까? 감사
Scaramouche '

16

이미 Lodash를 사용하고 있다면 키와 값을 모두 포함하는이 간단한 접근 방식을 수행 할 수 있습니다.

<ul>
  <li *ngFor='let key of _.keys(demo)'>{{key}}: {{demo[key]}}</li>
</ul>

타이프 스크립트 파일에 다음을 포함하십시오.

import * as _ from 'lodash';

내 보낸 구성 요소에 다음을 포함하십시오.

_: any = _;

죄송하지만 Lodash와 같은 추가 라이브러리를 사용할 필요는 없습니다. 어쨌든 새로운 방법은 항상 환영합니다 :)
Pardeep Jain

8

파이프에 감사하지만 각도 2 RC5에서 사용할 수 있기 전에 약간 변경해야했습니다. 파이프 가져 오기 행을 변경하고 키 배열 초기화에 모든 유형을 추가했습니다.

 import {Pipe, PipeTransform} from '@angular/core';

 @Pipe({name: 'keys'})
 export class KeysPipe implements PipeTransform {
 transform(value) {
   let keys:any = [];
   for (let key in value) {
      keys.push( {key: key, value: value[key]} );
    }
     return keys;
  }
}

네 수입이 변경되었습니다
Pardeep Jain

7

여기에 대한 답변 중 어느 것도 상자에서 나에게 도움이되지 않았습니다.

pipes/keys.ts내용으로 작성 :

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform
{
    transform(value:any, args:string[]): any {
        let keys:any[] = [];
        for (let key in value) {
            keys.push({key: key, value: value[key]});
        }
        return keys;
    }
}

다음에 추가하십시오 app.module.ts(주 모듈) :

import { KeysPipe } from './pipes/keys';

그런 다음 모듈 선언에 다음과 같이 추가하십시오.

@NgModule({
    declarations: [
        KeysPipe
    ]
})
export class AppModule {}

그런 다음 뷰 템플릿에서 다음과 같은 것을 사용할 수 있습니다.

<option *ngFor="let entry of (myData | keys)" value="{{ entry.key }}">{{ entry.value }}</option>

여기에 좀 더 읽으려면 내가 찾은 좋은 참조입니다.


귀하의 답변과 위에 제공된 다른 답변 (파이프 만 사용) 간의 차이점이 무엇인지 알 수 있습니까? 위와 동일
Pardeep Jain

1
물론 1. 위의 예제는 * ngFor = "let entry of"대신 * ngFor = "# entry"를 사용하고 컴파일러에서 #entry 구문을 허용하지 않으므로 참조도 #을 사용하지 않습니다. "(myData | 키) 입력"이 더 나은 솔루션 인 것 같습니다. 2. 내 컴파일러는 명시적인 데이터 유형이 누락되어 파이프 클래스 예제의 유효성을 검사하지 않았으므로 추가했습니다. 3. 위의 예제는 파이프를 내 대답이하는 프로젝트에 통합하는 방법을 보여주지 않으므로 메인 모듈로 가져와야합니다.
cjohansson

haha yes offcourese, 그 당시에 답변을 받았을 때 #등을 포함한 구문 . btw 당신의 답변도 틀림 없습니다.
Pardeep Jain

6

다른 멋진 파이프 중에서 이것을 수행하는 멋진 라이브러리가 있습니다. 그것은 ~라고 불린다ngx-pipes 합니다.

예를 들어 키 파이프는 객체의 키를 반환하고 값 파이프는 객체의 값을 반환합니다.

키 파이프

<div *ngFor="let key of {foo: 1, bar: 2} | keys">{{key}}</div> 
<!-- Output: 'foo' and 'bar -->

가치관

<div *ngFor="let value of {foo: 1, bar: 2} | values">{{value}}</div>
<!-- Output: 1 and 2 -->

사용자 정의 파이프를 만들 필요가 없습니다. :)


2
좋은 대안이지만 파이프와 같은 간단한 코드를 사용하여 코드를 간단하게 작성하기 위해 외부 라이브러리를 사용하는 이유는 무엇입니까
Pardeep Jain

2
음 ... 근데 파이프인가요? 패키지를 가져올 때 package.json의 한 줄과 모듈의 다른 두 줄입니다. 반면, 사용자 지정 파이프에는 10-20 줄의 코드와 모듈의 가져 오기 줄이있는 별도의 파일이 필요합니다. 프로젝트에서 ngx- 파이프를 사용하는 것이 매우 쉽다는 것을 알게되었습니다. 우리는 왜 바퀴를 재발 명해야합니까? :)
RichieRock

네, 의심 할 여지없이 실제로 그 의견에 근거하여이 둘 중 하나를 선택할 수 있습니다.
Pardeep Jain

2
사용자 지정 파이프를 작성하는 경우 해당 사용자 지정 파이프 테스트해야합니다 . 파이프 코드를 테스트하기 위해 10-20 줄의 파이프 코드가 있고 아마도 20-40 줄의 테스트 코드입니다.
danwellman

4

색인 사용 :

<div *ngFor="let value of Objects; index as key">

용법:

{{key}} -> {{value}}

1
그것은 나에게 새로운 것입니다. 더 나은 답변과 함께 예제를 추가 할 수 있다면 :) 또한 같은 문서를 알려 주시겠습니까?
Pardeep Jain

객체의 유형은 무엇입니까? 배열 또는 맵? 명확하게 작성하십시오. 미리 감사드립니다
Basil Mohammed

3

간단한 해결책은 다음과 같습니다.

이것을 위해 타이프 스크립트 반복자를 사용할 수 있습니다

import {Component} from 'angular2/core';
declare var Symbol;
@Component({
    selector: 'my-app',
    template:`<div>
    <h4>Iterating an Object using Typescript Symbol</h4><br>
Object is : <p>{{obj | json}}</p>
</div>
============================<br>
Iterated object params are:
<div *ngFor="#o of obj">
{{o}}
</div>

`
})
export class AppComponent {
  public obj: any = {
    "type1": ["A1", "A2", "A3","A4"],
    "type2": ["B1"],
    "type3": ["C1"],
    "type4": ["D1","D2"]
  };

  constructor() {
    this.obj[Symbol.iterator] =  () => {
          let i =0;

          return {
            next: () => {
              i++;
              return {
                  done: i > 4?true:false,
                  value: this.obj['type'+i]
              }
            }
          }
    };
  }
}

http://plnkr.co/edit/GpmX8g?p=info


3

데모 유형을 배열로 변경하거나 객체를 반복하고 다른 배열로 푸시

public details =[];   
Object.keys(demo).forEach(key => {
      this.details.push({"key":key,"value":demo[key]);
    });

그리고 HTML에서 :

<div *ngFor="obj of details">
  <p>{{obj.key}}</p>
  <p>{{obj.value}}</p>
  <p></p>
</div>

이것은 적절한 방법이 아니며, 누구나 쉽게 수행 할 수 있습니다.
Pardeep Jain

1

Object.keys 가이 문제에 대한 최상의 솔루션이라고 생각합니다. 이 답변을 발견하고 Object.keys가 [ 'key1', 'key2'] 대신 [ '0', '1']을 제공하는 이유를 찾으려고 노력하는 사람은 다음과 같이주의해야합니다. " of "및"in ":

나는 이미 비슷한 Object.keys를 사용하고 있었다 :

interface demo {
    key: string;
    value: string;
}

createDemo(mydemo: any): Array<demo> {
    const tempdemo: Array<demo> = [];

    // Caution: use "of" and not "in"
    for (const key of Object.keys(mydemo)) {
        tempdemo.push(
            { key: key, value: mydemo[key]}
        );
    }

    return tempdemo;
}

그러나 대신

for (const key OF Object.keys(mydemo)) {

실수로 썼다

for (const key IN Object.keys(mydemo)) {

어떤 오류없이 완벽하게 "작동"하고 반환

[{key: '0', value: undefined}, {key: '1', value: undefined}]

인터넷 검색과 저주에 약 2 시간이 걸렸습니다.

(이마 때리고)


1

이것을 시도하여 동적 객체의 키 를 얻을 수 있습니다

myObj['key']

0

지금은 이렇게해야합니다. 파이어베이스에서받은 객체를 변환하고 싶지 않기 때문에 매우 효율적이지 않습니다.

    this.af.database.list('/data/' + this.base64Email).subscribe(years => {
        years.forEach(year => {

            var localYears = [];

            Object.keys(year).forEach(month => {
                localYears.push(year[month])
            });

            year.months = localYears;

        })

        this.years = years;

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