0
votes

I have the next issue in angular:

I have this json as entity:

{
    "id": 1,
    "value": "I am ok"
}

I have my own model as json like :

[{
   "Field": "id",
   "ReadOnly": true,
   "BackColor": "silver",
   "Type": "Text"
},{
   "Field": "value",
   "ReadOnly": true,
   "BackColor": "silver",
   "Type": "Text"
}]

Once I get the correct information in the subscription (first json I showed you), I am making, in the template of the component, a loop of model to configure the dialog and I am using matInput to show the values.

Ok I am trying to build something like:

<div *ngFor="let col of row.data" class="col-{{col.ColType}}-{{col.Col}}"  [ngSwitch]="col.Type" style="width: 100% !important">

</div>

row.data is each col of the model converted to array.

Inside div I am making something like:

<mat-form-field *ngFor="let data of classe.Data"> 
    <input matInput [(ngModel)]="data[col.Field.toLowerCase()]" [name]="col.Field.toLowerCase()" >
</mat-form-field>

classe.Data is the class of first json I wrote.

I am getting the next error:

core.js:7187 ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

Do I have other way to avoid this error? I would like to use ngModel but if not possible I am open to use other way.

Thx

3
Are you trying to show just 2 input boxes? one for the id and one for the value? - nash11

3 Answers

1
votes

try out angular's KeyValuePipe (https://angular.io/api/common/KeyValuePipe). It transforms objects or maps into an array of key value pairs which you can use with ngFor if you don't have an array.

Here is an example how to iterate properties of an array, map and object.

Component:

...
export class AppComponent  {
  name = 'Angular';

  arr:string[] =["foo", "bar"];
  map = new Map([[2, 'foo'], [1, 'bar']]);
  object: {[key: number]: string} = {2: 'foo', 1: 'bar'};
}

Template:

<h2>Iterate array</h2>
    <div *ngFor="let item of arr | keyvalue">
      {{item.key}}:{{item.value}}
    </div>

<h2>Iterate through a map</h2>
    <div *ngFor="let item of map | keyvalue">
      {{item.key}}:{{item.value}}
    </div>

<h2>Iterate over object properties</h2>
    <div *ngFor="let item of object | keyvalue">
      {{item.key}}:{{item.value}}
    </div>

Output:

Iterate array
0:foo
1:bar

Iterate through a map
1:bar
2:foo

Iterate over object properties
1:bar
2:foo

Stackblitz: https://stackblitz.com/edit/angular-gf7yas

If you remove the keyvalue-pipe from the last two examples, so you try to iterate over an object and a map, you will get the error:

Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

0
votes

I'm not sure what your final template is but I don't think you even need the second ngFor. With two ngFor, you will end up getting four inputs in total while you only have two parameters. I'm guessing you just need two inputs, one for the id and one for the value.

Try this if that is your requirement

<div *ngFor="let col of row.data" class="col-{{col.ColType}}-{{col.Col}}" [ngSwitch]="col.Type" style="width: 100% !important">
    <mat-form-field>
        <input matInput [(ngModel)]="classe.Data[col.Field.toLowerCase()]" [name]="col.Field.toLowerCase()" >
    </mat-form-field>
</div>
0
votes

A good way I found is using events:

In the component I wrote:

onKey = (field: string, ev) => {
    this.classe.Data[field.toLowerCase()] = ev.target.value;
}

and template will be:

<mat-form-field> 
    <mat-label>{{col.Translate | translate}}</mat-label>                                              
    <input matInput 
        (keyup)="onKey(col.Field.toLowerCase(), $event)" 
        [name]="col.Field.toLowerCase()" 
        [value]="classe.Data[col.Field.toLowerCase()]">
</mat-form-field> 

It is one solution for me. I would love to use ngModel but ...