Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can ngForIn be used in angular 4?

I am trying to iterate over the properties of an object using *ngFor but using in. When I try to do this

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

I get the error message:

Can't bind to 'ngForIn' since it isn't a known property of 'li'.

I have included FormsModule and BrowserModule in the imports section of the @NgModule for this component.

Is it possible to use ngForIn on li and if not is there an idiomatic alternative?

like image 849
Eli Sadoff Avatar asked Jul 17 '17 18:07

Eli Sadoff


2 Answers

As AJT_82 mentioned in comment you can create special directive for such purposes. It will be based on NgForOf<T> directive:

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

like image 190
yurzui Avatar answered Nov 06 '22 17:11

yurzui


The easiest approach would be to turn your object into an array using Object.values() and Object.keys(). Check out this plunker for an example.

If you want access to the keys as well as the value you can include an index in your *ngFor.

Template:

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

Component 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);
  }
}
like image 3
Z. Bagley Avatar answered Nov 06 '22 17:11

Z. Bagley