program story

Angular에서 객체 반복

inputbox 2020. 8. 6. 08:20
반응형

Angular에서 객체 반복


Angular 2 Alpha 28에서 몇 가지 일을하려고하는데 사전 및 NgFor에 문제가 있습니다.

TypeScript에 다음과 같은 인터페이스가 있습니다.

interface Dictionary {
    [ index: string ]: string
}

JavaScript에서 이것은 데이터가 다음과 같은 객체로 변환됩니다.

myDict={'key1':'value1','key2':'value2'}

나는 이것을 반복하고 이것을 시도하고 싶다 :

<div *ngFor="(#key, #value) of myDict">{{key}}:{{value}}</div>

그러나 아무 소용이 없으면 아래 중 어느 것도 작동하지 않았습니다.

<div *ngFor="#value of myDict">{{value}}</div>
<div *ngFor="#value of myDict #key=index">{{key}}:{{value}}</div>

모든 경우에 "예기치 않은 토큰"또는 " 'iterableDiff'파이프 지원 오브젝트를 찾을 수 없습니다"와 같은 오류가 발생합니다.

내가 여기서 무엇을 놓치고 있습니까? 더 이상 불가능합니까? (첫 번째 구문은 Angular 1.x에서 작동합니다) 또는 객체를 반복하는 구문이 다른가요?


ng1의 구문을 지원하지 않으려는 것 같습니다.

Miško Hevery에 따르면 ( reference ) :

키에 키가없는 맵이 있으므로 반복을 예측할 수 없습니다. 이것은 ng1에서 지원되었지만 실수라고 생각하고 NG2에서 지원되지 않습니다

계획은 mapToIterable 파이프를 갖는 것입니다

<div *ngFor"var item of map | mapToIterable">

따라서 객체를 반복하려면 "파이프"를 사용해야합니다. 현재 구현 된 파이프 가 없습니다 .

해결 방법으로 다음은 키를 반복하는 작은 예입니다.

구성 요소:

import {Component} from 'angular2/core';

@Component({
  selector: 'component',
  templateUrl: `
       <ul>
       <li *ngFor="#key of keys();">{{key}}:{{myDict[key]}}</li>
       </ul>
  `
})
export class Home {
  myDict : Dictionary;
  constructor() {
    this.myDict = {'key1':'value1','key2':'value2'};
  }

  keys() : Array<string> {
    return Object.keys(this.myDict);
  }
}

interface Dictionary {
    [ index: string ]: string
}

각도 6.1.0+ 답변

다음과 같이 내장 keyvalue파이프를 사용하십시오 .

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

또는 이와 같이 :

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

파일의 위치 mySortingFunction는 다음과 .ts같습니다.

mySortingFunction = (a, b) => {
  return a.key > b.key ? -1 : 1;
}

Stackblitz : https://stackblitz.com/edit/angular-iterate-key-value

앵귤러 파이프는 모든 템플릿에서 즉시 사용할 수 있으므로 모듈에 이것을 등록 할 필요는 없습니다.

Javascript-Maps 에서도 작동합니다 .


사전 각도 6 답변

다른 답변에서 언급했듯이 ngx에서는 지원되지 않으므로 키-값 쌍에 대한 해결 방법이 있습니다 .

파이프 :

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'mapToIterable'
})
export class MapToIterable implements PipeTransform {
  transform(dict: Object) {
    var a = [];
    for (var key in dict) {
      if (dict.hasOwnProperty(key)) {
        a.push({key: key, val: dict[key]});
      }
    }
    return a;
  }
}

사용법 :

<div *ngFor="let keyValuePair of someObject | mapToIterable">
  This is the key {{keyValuePair.key}} and this is the value {{keyValuePair.val}}.
</div>

Stackblitz 예 : https://stackblitz.com/edit/map-to-iterable-pipe


이 파이프를 사용해보십시오

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

@Pipe({ name: 'values',  pure: false })
export class ValuesPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value).map(key => value[key]);
  }
}

<div *ngFor="#value of object | values"> </div>

@obscur의 답변 외에도 @View에서 keyvalue@View 모두에 액세스하는 방법 의 예가 있습니다.

파이프:

@Pipe({
   name: 'keyValueFilter'
})

export class keyValueFilterPipe {
    transform(value: any, args: any[] = null): any {

        return Object.keys(value).map(function(key) {
            let pair = {};
            let k = 'key';
            let v = 'value'


            pair[k] = key;
            pair[v] = value[key];

            return pair;
        });
    }

}

전망:

<li *ngFor="let u of myObject | 
keyValueFilter">First Name: {{u.key}} <br> Last Name: {{u.value}}</li>

따라서 객체가 다음과 같으면

myObject = {
    Daario: Naharis,
    Victarion: Greyjoy,
    Quentyn: Ball
}

생성 된 결과는 다음과 같습니다.

이름 : Daario
성 : Naharis

이름 : Victarion
성 : Greyjoy

이름 : Quentyn
성 : Ball


SimonHawesome의 훌륭한 답변에 추가하십시오 . 새로운 타이프 스크립트 기능 중 일부를 활용하는 간결한 버전을 만들었습니다. SimonHawesome의 버전은 기본 세부 사항을 설명하기 위해 의도적으로 상세하다는 것을 알고 있습니다. 파이프가 잘못된 값으로 작동하도록 초기 검사를 추가했습니다 . 예를 들어지도가 null입니다.

반복자 변환을 사용하면 (여기에서 수행 한 것처럼) 임시 배열에 메모리를 할당 할 필요가 없으므로 (다른 답변 중 일부에서 수행됨) 더 효율적일 수 있습니다.

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

@Pipe({
    name: 'mapToIterable'
})
export class MapToIterable implements PipeTransform {
    transform(map: { [key: string]: any }, ...parameters: any[]) {
        if (!map)
            return undefined;
        return Object.keys(map)
            .map((key) => ({ 'key': key, 'value': map[key] }));
    }
}

다음은 여러 변환 (keyval, key, value)을 지원하는 위의 답변 중 일부에 대한 변형입니다.

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

type Args = 'keyval'|'key'|'value';

@Pipe({
  name: 'mapToIterable',
  pure: false
})
export class MapToIterablePipe implements PipeTransform {
  transform(obj: {}, arg: Args = 'keyval') {
    return arg === 'keyval' ?
        Object.keys(obj).map(key => ({key: key, value: obj[key]})) :
      arg === 'key' ?
        Object.keys(obj) :
      arg === 'value' ?
        Object.keys(obj).map(key => obj[key]) :
      null;
  }
}

용법

map = {
    'a': 'aee',
    'b': 'bee',
    'c': 'see'
}

<div *ngFor="let o of map | mapToIterable">{{o.key}}: {{o.value}}</div>
  <div>a: aee</div>
  <div>b: bee</div>
  <div>c: see</div>

<div *ngFor="let o of map | mapToIterable:'keyval'">{{o.key}}: {{o.value}}</div>
  <div>a: aee</div>
  <div>b: bee</div>
  <div>c: see</div>

<div *ngFor="let k of map | mapToIterable:'key'">{{k}}</div>
  <div>a</div>
  <div>b</div>
  <div>c</div>

<div *ngFor="let v of map | mapToIterable:'value'">{{v}}</div>
  <div>aee</div>
  <div>bee</div>
  <div>see</div>

업데이트 : Angular는 이제 다음을 통해 json 객체를 통해 파이프를 제공합니다 keyvalue.

<div *ngFor="let item of myDict | keyvalue">
  {{item.key}}:{{item.value}}
</div>

작업 데모 및 자세한 내용을 보려면


이전 (이전 버전의 경우) : 지금까지 내가 찾은 가장 좋은 / 가장 짧은 대답은 (구성 요소 측에서 파이프 필터 또는 사용자 정의 기능이 없음)입니다.

구성 요소 측 :

objectKeys = Object.keys;

템플릿 측면 :

<div *ngFor='let key of objectKeys(jsonObj)'>
   Key: {{key}}

    <div *ngFor='let obj of jsonObj[key]'>
        {{ obj.title }}
        {{ obj.desc }}
    </div>

</div>

작업 데모


비슷한 문제가있어서 객체와지도를 위해 무언가를 만들었습니다.

import { Pipe } from 'angular2/core.js';

/**
 * Map to Iteratble Pipe
 * 
 * It accepts Objects and [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
 * 
 * Example:
 * 
 *  <div *ngFor="#keyValuePair of someObject | mapToIterable">
 *    key {{keyValuePair.key}} and value {{keyValuePair.value}}
 *  </div>
 * 
 */
@Pipe({ name: 'mapToIterable' })
export class MapToIterable {
  transform(value) {
    let result = [];
    
    if(value.entries) {
      for (var [key, value] of value.entries()) {
        result.push({ key, value });
      }
    } else {
      for(let key in value) {
        result.push({ key, value: value[key] });
      }
    }

    return result;
  }
}


Angular 2.x 및 & Angular 4.x는 즉시 이것을 지원하지 않습니다

이 두 파이프를 사용하여 또는 별로 반복 할 수 있습니다 .

키 파이프 :

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

@Pipe({
  name: 'keys',
  pure: false
})
export class KeysPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value)
  }
}

가치관 :

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

@Pipe({
  name: 'values',
  pure: false
})
export class ValuesPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value).map(key => value[key])
  }
}

사용하는 방법:

let data = {key1: 'value1', key2: 'value2'}

<div *ngFor="let key of data | keys"></div>
<div *ngFor="let value of data | values"></div>

누군가가 다차원 객체로 작업하는 방법을 궁금해하는 경우 여기 해결책이 있습니다.

서비스에 다음과 같은 객체가 있다고 가정 해 봅시다.

getChallenges() {
    var objects = {};
    objects['0'] = { 
        title: 'Angular2', 
        description : "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
    };

    objects['1'] = { 
        title: 'AngularJS', 
        description : "Lorem Ipsum is simply dummy text of the printing and typesetting industry."
    };

    objects['2'] = { 
        title: 'Bootstrap',
        description : "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
    };
    return objects;
}

구성 요소에서 다음 기능 추가

challenges;

constructor(testService : TestService){
    this.challenges = testService.getChallenges();
}
keys() : Array<string> {
    return Object.keys(this.challenges);
}

마지막으로 다음을 수행하십시오.

<div *ngFor="#key of keys();">
    <h4 class="heading">{{challenges[key].title}}</h4>
    <p class="description">{{challenges[key].description}}</p>
</div>

JSON 쿼리 / API 호출에서 반환 된 데이터를 구문 분석하고 사용하려고 시도하면서 머리카락을 찢어 냈습니다. 내가 잘못 가고있는 곳을 정확히 모르는 경우, 여러 가지 오류 코드를 쫓아 며칠 동안 대답을 돌고있는 것처럼 느낍니다.

" 'iterableDiff'파이프 지원 오브젝트를 찾을 수 없습니다"

"일반 TYpe 배열에는 하나의 인수가 필요합니다"

JSON 구문 분석 오류

방금 잘못된 수정 조합이 있다고 가정합니다.

여기 몇 가지 문제점과 요약이 요약되어 있습니다.

먼저 api 호출의 결과를 확인하십시오. 결과는 객체, 배열 또는 객체 배열의 형태 일 수 있습니다.

나는 그것에 너무 많이 들어 가지 않을 것입니다. 반복 가능하지 않다는 OP의 원래 오류는 일반적으로 배열이 아닌 객체를 반복하려고하면 발생합니다.

다음은 배열과 객체의 변수를 보여주는 디버깅 결과 중 일부입니다.

따라서 일반적으로 JSON 결과를 반복하려면 Array 형식인지 확인해야합니다. 나는 많은 예제를 시도해 보았고 아마도 내가 지금 알고있는 것을 실제로 알고있을 것입니다. 그러나 내가 겪은 접근 방식은 실제로 파이프를 구현하는 것이었고 사용한 코드는 t.888에 의해 게시 된 것입니다.

   transform(obj: {[key: string]: any}, arg: string) {
if (!obj)
        return undefined;

return arg === 'keyval' ?
    Object.keys(obj).map((key) => ({ 'key': key, 'value': obj[key] })) :
  arg === 'key' ?
    Object.keys(obj) :
  arg === 'value' ?
    Object.keys(obj).map(key => obj[key]) :
  null;

솔직히 나는 'undefined undefined'호출을 추가하여 오류 처리가 부족하다고 생각합니다. 현재 예상치 못한 데이터를 파이프로 보낼 수 있다고 생각합니다. .

파이프에 대한 인수를 다루고 싶지 않다면 (그리고 대부분의 경우 필요하지 않다고 생각하면) 다음을 반환 할 수 있습니다

       if (!obj)
          return undefined;
       return Object.keys(obj);

해당 파이프를 사용하는 파이프 및 페이지 또는 구성 요소 작성에 대한 참고 사항

'name_of_my_pipe'를 찾을 수 없다는 오류가 발생했습니다

CLI에서 'ionic generate pipe'명령을 사용하여 파이프 모듈 .ts가 올바르게 작성되고 참조되는지 확인하십시오. mypage.module.ts 페이지에 다음을 추가하십시오.

import { PipesModule } from ‘…/…/pipes/pipes.module’;

(자신의 custom_module도 가지고 있다면 이것이 변경되는지 확실하지 않으면 custommodule.module.ts에 추가해야 할 수도 있습니다)

'ionic generate page'명령을 사용하여 페이지를 만들었지 만 해당 페이지를 기본 페이지로 사용하기로 결정한 경우 app.module.ts에서 페이지 참조를 제거해야합니다 (여기에서 https 와 관련하여 게시 한 다른 답변이 있습니다 ./ /forum.ionicframework.com/t/solved-pipe-not-found-in-custom-component-/95179/13?u=dreaser

html 파일에 데이터를 표시하는 여러 가지 방법이 있으며 그 차이점을 설명하기에 충분하지 않은 답변을 검색 할 때. 특정 시나리오에서 서로를 사용하는 것이 더 좋습니다.

            <ion-item *ngFor="let myPost of posts">
                  <img src="https://somwhereOnTheInternet/{{myPost.ImageUrl}}"/>
                  <img src="https://somwhereOnTheInternet/{{posts[myPost].ImageUrl}}"/>
                  <img [src]="'https://somwhereOnTheInternet/' + myPost.ImageUrl" />
            </ion-item>

그러나 효과가 있었으므로 값과 키를 모두 표시 할 수있었습니다.

    <ion-list>  
      <ion-item *ngFor="let myPost of posts  | name_of_pip:'optional_Str_Varible'">

        <h2>Key Value = {{posts[myPost]}} 

        <h2>Key Name = {{myPost}} </h2>

      </ion-item>
   </ion-list>  

API 호출을 만들려면 HttpModule을 app.module.ts로 가져와야하는 것처럼 보입니다.

import { HttpModule } from '@angular/http';
 .
 .  
 imports: [
BrowserModule,
HttpModule,

호출하는 페이지에서 Http가 필요합니다.

import {Http} from '@angular/http';

API 호출을 할 때 자식 데이터 (배열 내의 객체 또는 배열)에 두 가지 다른 방법으로 얻을 수있는 것처럼 보입니다.

통화 중

this.http.get('https://SomeWebsiteWithAPI').map(res => res.json().anyChildren.OrSubChildren).subscribe(
        myData => {

또는 지역 변수에 데이터를 할당 할 때

posts: Array<String>;    
this.posts = myData['anyChildren'];

(그 변수가 배열 문자열이어야하는지 확실하지 않지만, 지금 내가 가지고있는 것입니다. 더 일반적인 변수로 작동 할 수 있습니다)

마지막으로 내장 JSON 라이브러리를 사용할 필요는 없지만 객체에서 문자열로 또는 그 반대로 변환하는 데이 두 호출이 편리하다는 것을 알 수 있습니다

        var stringifiedData = JSON.stringify(this.movies);                  
        console.log("**mResults in Stringify");
        console.log(stringifiedData);

        var mResults = JSON.parse(<string>stringifiedData);
        console.log("**mResults in a JSON");
        console.log(mResults);

이 정보 모음이 누군가를 돕기를 바랍니다.


JavaScript에서는 데이터가 다음과 같은 객체로 변환됩니다.

TypeScript의 인터페이스는 개발 시간 구성입니다 (순전히 툴링 ... 0 런타임 영향). JavaScript와 동일한 TypeScript를 작성해야합니다.


사전은 배열이 아니라 객체입니다. ng-repeat에는 Angular 2의 배열이 필요하다고 생각합니다.

가장 간단한 해결책은 객체를 즉시 배열로 변환하는 파이프 / 필터를 만드는 것입니다. 즉, @basarat이 말한 것처럼 배열을 사용하고 싶을 것입니다.


당신이있는 경우 es6-shim또는 tsconfig.json대상 es6, 당신은 ES6 사용할 수있는 지도 를 만들 수 있습니다.

var myDict = new Map();
myDict.set('key1','value1');
myDict.set('key2','value2');

<div *ngFor="let keyVal of myDict.entries()">
    key:{{keyVal[0]}}, val:{{keyVal[1]}}
</div>

PipeTransform을 정의 MapValuesPipe하고 구현 하십시오 .

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

@Pipe({name: 'mapValuesPipe'})
export class MapValuesPipe implements PipeTransform {
    transform(value: any, args?: any[]): Object[] {
        let mArray: 
        value.forEach((key, val) => {
            mArray.push({
                mKey: key,
                mValue: val
            });
        });

        return mArray;
    }
}

파이프 모듈에 파이프를 추가하십시오. 둘 이상의 구성 요소에 동일한 파이프 를 사용해야하는 경우 중요합니다 .

@NgModule({
  imports: [
    CommonModule
  ],
  exports: [
    ...
    MapValuesPipe
  ],
  declarations: [..., MapValuesPipe, ...]
})
export class PipesAggrModule {}

그런 다음 html에서 다음과 같이 파이프를 사용하십시오 *ngFor.

<tr *ngFor="let attribute of mMap | mapValuesPipe">

파이프를 사용하려는 컴포넌트에서 PipesModule을 선언해야합니다.

@NgModule({
  imports: [
    CommonModule,
    PipesAggrModule
  ],
...
}
export class MyModule {}

//Get solution for ng-repeat    
//Add variable and assign with Object.key

    export class TestComponent implements OnInit{
      objectKeys = Object.keys;
      obj: object = {
        "test": "value"
        "test1": "value1"
        }
    }
    //HTML
      <div *ngFor="let key of objectKeys(obj)">
        <div>
          <div class="content">{{key}}</div>
          <div class="content">{{obj[key]}}</div>
        </div>

그래서 Object (obj) .keys.length 만 반환하는 자체 도우미 함수 objLength (obj)를 구현하려고했습니다. 그러나 템플릿 * ngIf 함수에 추가 할 때 IDE에서 objectKeys ()를 제안했습니다. 나는 그것을 시도했고 효과가 있었다. 선언에 따라 lib.es5.d.ts에서 제공하는 것처럼 보입니다.

구현 방법은 다음과 같습니다 (서버 측에서 생성 한 키를 업로드 한 파일의 인덱스로 사용하는 사용자 정의 객체가 있습니다).

        <div *ngIf="fileList !== undefined && objectKeys(fileList).length > 0">
          <h6>Attached Files</h6>
          <table cellpadding="0" cellspacing="0">
            <tr *ngFor="let file of fileList | keyvalue">
              <td><a href="#">{{file.value['fileName']}}</a></td>
              <td class="actions">
                <a title="Delete File" (click)="deleteAFile(file.key);">
                </a>
              </td>
            </tr>
          </table>
        </div>

참고 URL : https://stackoverflow.com/questions/31490713/iterate-over-object-in-angular

반응형