skip to Main Content

Pretty new to Angular and trying to attach a rest API from a WordPress DB into my app. Having issues looping through the object returned to the service call. I can print it out to the view but when I try to loop through it I get this error:

"ERROR Error: Error trying to diff ‘[object Object]’. Only arrays and iterables are allowed"

Example data:

{
  "acf": {
    "email_address": "[email protected]",
    "favicon": false,
    "favicon_png": false,
    "socialmedia_github": "https://www.github.com/"
    "socialmedia_instagram": ""
    "socialmedia_linkedin: "https://www.linkedin.com/"

  }
}

Service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable} from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class WpOptionsService {
  apiURL = '//myurl.com/wp-json/acf/v3';

  getOptions(): Observable<WpOptions[]> {
    return this.http.get<WpOptions[]>(`${this.apiURL}/options/options`)
  }

  constructor(private http: HttpClient) { }
}

export class WpOptions {
  postID: any
}

Component:

import { Component, OnInit } from '@angular/core';
import { WpOptionsService, WpOptions } from '../../services/wp-options.service'

@Component({
  selector: 'app-splash',
  templateUrl: './splash.component.html',
  styleUrls: ['./splash.component.scss']
})
export class SplashComponent implements OnInit {

  options:WpOptions[] = [];

  constructor(private WpOptionsService: WpOptionsService) { }

  ngOnInit(): void {
    this.WpOptionsService.getOptions().subscribe(optionList => {
      this.options = optionList;
      console.log(typeof this.options);
      console.log(this.options);
    })
  }

}

View/HTML:

<div *ngFor="let option of options">

</div>

<pre> 
  <code>
     {{ options | json }}
  </code>
</pre>

2

Answers


  1. Chosen as BEST ANSWER

    Found a solution by iterating through the keys to map an array.

    Component:

    export class SplashComponent implements OnInit {
    
      options:WpOptions[] = [];
    
      generateArray(obj:any){
        return Object.keys(obj).map((key)=>{
          return obj[key]
        });
      }
    
      constructor(private WpOptionsService: WpOptionsService) { }
    
      ngOnInit(): void {
        this.WpOptionsService.getOptions().subscribe(optionList => {
          this.options = this.generateArray(optionList);
        })
      }
    
    }
    

    And then within the component HTML I can loop through it as I original expected. I can also reach deeper objects

    <div *ngFor="let option of generateArray(options)">
    
      {{option.site_email}}
    
      <div *ngFor="let prof_repeater of generateArray(option.prof_repeater)">
    
        {{prof_repeater.prof_tax.name}}
      
      </div>
    
    </div>
    

  2. you cannot do this because its not an array – when one is presenting an object to an ngfor statement it is expecting to loop through an array.

    In your particular instance you can strong type to the object using handlebars.

     "acf": {
        "email_address": "[email protected]",
        "favicon": false,
        "favicon_png": false,
        "socialmedia_github": "https://www.github.com/"
        "socialmedia_instagram": ""
        "socialmedia_linkedin: "https://www.linkedin.com/"
    
      }
    

    becomes:

    {{(afc)?.email_address}} as an example. make sure you use the question mark or you will receive errors because angular is not so patient for the data at first.

    If you wanted to take this data and force it to an ngFor loop you can push it to an array – then you could use optionArray on your ngFor

    component typescript

    optionArray!: any[]
      constructor() { }
    
      ngOnInit(): void {
        this.WpOptionsService.getOptions().subscribe(optionList => {
          // this.options = optionList;
        optionList.forEach((option:any)=>{
           this.optionArray.push(option)
        })
          console.log(typeof this.options);
          console.log(this.options);
        })
      }
      }
    

    component html

    <ng-container>
    <div *ngFor="let option of optionArray; let i = index">
    {{option?.afc?.email_address}} {{i}}
    </div>
    </ng-container>
    

    this won’t be exact but pretty close to what you want.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search