Error: trying to diff *ngFor

After converting a JSON object to an array and using *ngFor to repeat options in a select box, I am getting an “Error: trying to diff” message.

Here is my view code.

<ion-option *ngFor="let urge of urges;let i=index" ngValue="{{urge.name}}">{{urge.name}}</ion-option>

Here is my controller code.

export class SignupPage {

  private http:Http;
  private urges=[];

  constructor(nav:NavController, http:Http) {
    /*
    Get all urges
     */

    http.get('http://localhost:8000/urges/all')
    // Call map on the response observable to get the parsed people object
        .map(result => result.json())
        // Subscribe to the observable to get the parsed  object and attach it to the
        // component
        .subscribe(urges => {

          for(var i=0;i<urges.length;i++){

            this.urges.push(urges[i]);
          }

          console.log(this.urges);
        },error=>console.log(error)
        );
  }

}

A bit off.

Try this.

<ion-option *ngFor="let urge of urges;let i=index" [value]="urge.name">{{urge.name}}</ion-option>

It did not work. I get Error trying to diff in response

The error fires when I click the ok button confirming the select box selection.

May we see the exact JSON that is coming from the backend? I suspect that either it might not be an array or that you’ve got duplicate items.

This is what console.log returns for this.urges

It is an array of objects

I tried using a custom pipe to convert the result.json() data, but I am not sure exactly how I should accomplish this or what I should convert the object to.

Is there a way to receive an array instead of a json object from a get request?

Can you post the entire view code? I cannot replicate the problem just dropping this into the bottom of tab1 of the tabs starter project:

  <ion-select>
  <ion-option *ngFor="let urge of urges; let i=index" [value]="urge.name">{{urge.name}}</ion-option>
  </ion-select>
  private urges = [
    {name: 'a'},
    {name: 'b'},
    {name: 'c'},
  ];

Even if there are duplicate names in urges, I get no errors.

<!--
  Generated template for the SignupPage page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
-->
<ion-navbar *navbar>
    <ion-title>Signup</ion-title>
</ion-navbar>

<ion-content overflow-scroll=”true”  padding class="signup">
    <ion-label align="center">Sign Up Below</ion-label>
    <ion-list>
        <ion-item>
            <ion-label fixed>Full Name</ion-label>
            <ion-input type="text" value="" clearInput></ion-input>
        </ion-item>
        <ion-item>
            <ion-label fixed>Username</ion-label>
            <ion-input type="text" value="" clearInput></ion-input>
        </ion-item>
        <ion-item>
            <ion-label fixed>Email</ion-label>
            <ion-input type="text" value="" clearInput></ion-input>
        </ion-item>
        <ion-item>
            <ion-label fixed>Password</ion-label>
            <ion-input type="password" value="" clearInput></ion-input>
        </ion-item>
        <ion-item>
            <ion-label fixed>Confirm</ion-label>
            <ion-input type="password" value="" clearInput></ion-input>
        </ion-item>
        <ion-item>
            <ion-label>What's Your Urge</ion-label>
          <ion-select [(ngModel)]="urges">
              <!-- <ion-option *ngFor="let urge of urges" ngValue="{{urge['name']}}">{{urge['name']}}</ion-option> -->
              <ion-option *ngFor="let urge of urges;let i=index" [value]="urge.name">{{urge.name}}</ion-option>

          </ion-select>
        </ion-item>

    </ion-list>
</ion-content>

Aha. There’s the problem. You want to have a separate variable here representing a single urge (that has been chosen from the select). You don’t want to be binding the select to the array.

As a side note, you don’t need to loop and push. You can just reassign what comes from the backend to the urges instance variable.

As another side note, for what are perhaps now largely historical reasons, returning naked arrays in JSON is frowned upon for security reasons. What I usually do is to return an object with a single property:

{
  "urges": [...]
}
2 Likes