ngForIn可用于角4吗?

时间:2017-07-17 18:36:42

标签: angular typescript ngfor

我正在尝试使用*ngFor但使用in来迭代对象的属性。当我尝试这样做时

@Controller({
  selector: 'sample-controller',
  template: `
    <ul>
      <li *ngFor="let i in obj">
        <b>{{i}}</b>: {{obj[i]}}
      </li>
    </ul>`
})
class SampleController {
  obj = {a: 1, b: 2}
}

我收到错误消息:

  

无法绑定到'ngForIn',因为它不是'li'的已知属性。

我已在FormsModule的{​​{1}}部分中为此组件添加了BrowserModuleimports

是否可以在@NgModule上使用ngForIn,如果没有,是否有惯用的选择?

4 个答案:

答案 0 :(得分:7)

正如评论中提到的AJT_82,您可以为此目的创建特殊指令。它将基于NgForOf<T>指令:

interface NgForInChanges extends SimpleChanges {
  ngForIn?: SimpleChange;
  ngForOf?: SimpleChange;
}

@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);
    }
  }
}

<强> Plunker Example

答案 1 :(得分:3)

最简单的方法是使用Object.values()Object.keys()将对象转换为数组。查看this plunker以获取示例。

如果您想要访问密钥和值,可以在*ngFor中添加索引。

<强>模板:

<ul>
  <li *ngFor="let item of array; let index = index;">
    <b>{{keys[index]}}</b> value: {{item}}, index: {{index}}
  </li>
</ul>

组件TypeScript:

export class App {
  obj = {a: 1, b: 2}
  array = [];
  keys = [];
  constructor() {
  }

  ngOnInit() {
  this.array = Object.values(this.obj);
  this.keys = Object.keys(this.obj);
  }
}

答案 2 :(得分:1)

事情已经发生了一些变化(在Angular 9中),所以yurzi的答案将行不通,但是在类似的行上,将'forOf'的值设置为'super.ngForOf'可以解决问题

import {   ContentChildren,   Directive,   Input,   IterableDiffers,   NgIterable,   OnChanges,   SimpleChanges,   TemplateRef,   ViewChildren,   ViewContainerRef } from "@angular/core";

import { NgForOf } from "@angular/common";

export interface Selectable<T> {   selected: boolean;   isActive: boolean; }

@Directive({   
 selector: "[optionsFor][[optionsForOf]]" }) 
 export class OptionsForDirective<T extends Selectable<any>,U extends NgIterable<T> = NgIterable<T>> 
     extends NgForOf<T, U> implements OnChanges {   

   _editMode = false;   
   _forOf: Array<Selectable<any>>;

  @Input()   
  set iefOptionsForOf(value: any) {
    this._forOf = value;
    console.log("set of: ", value);   
  }

  @Input()   
  set iefOptionsForEditMode(value: boolean) {
    this._editMode = value;
    console.log("set edit mode: ", value);   
  }

  constructor(
    public _viewContainer2: ViewContainerRef,
    public _templateRef2: TemplateRef<any>,
    public _differs2: IterableDiffers   ) {
    super(_viewContainer2, _templateRef2, _differs2);   
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes.optionsForOf) {
      const origNgForOf: Array<Selectable<any>> = this._forOf;
      let filtered = origNgForOf;
      if (origNgForOf) {
        filtered = origNgForOf.filter(s => {
          return this._editMode || s.isActive !== false;
        });
      }
      console.log("filtered", filtered);

      super.ngForOf = filtered as any;
    }   
  } 
}

答案 3 :(得分:0)

可以将

Object.keysObject.values分配给组件上的公共属性,然后将它们用作模板中的函数。例如

//somewhere in the component
public objectKeys = Object.keys;
public objectValues = Object.values;

//somewhere in template
...*ngFor="let key of objectKeys(someObject)"...