HolzbeinWilli
HolzbeinWilli

Reputation: 198

Angular 6 Error trying to diff '[object Object]'. Only arrays and iterables are allowed

I think my problem is that the API delivers an Object instead of an array. So I need to modify the Object to be an Array?

How could this be done?
Object.assign?
Or Pipe?
Does anyone have a proper example?

I am still learning Angular this is my second Project so I need some help ;)

thy so far !

Here is my code

Getting data from API ..can't change the API it delivers an Object

KnowledgeBaseService

    import {Injectable, OnInit} from '@angular/core';
    import { HttpClient, HttpErrorResponse, HttpHeaders, HttpRequest, HttpResponse} from '@angular/common/http';
    import {environment} from '../../environments/environment';
    import { WikiModel } from '../../models/wikiItems.model'
    import {catchError, map, take} from 'rxjs/operators';
    import {throwError} from 'rxjs';
    
    
    @Injectable()
    export class KnowledgeBaseService {
      wikiApiUrl: string = environment.wikiApiUrl;
      wikiList: WikiModel[] = [];
     constructor(
    
      protected http: HttpClient,) {}
    
        getwikiList() {
          return this.http.get(this.wikiApiUrl + "/list")
            .pipe(map((data: any[]) => {return this.wikiList = data;
                }), catchError(error => {
                return throwError('Its a Trap!')
              })
            );
        }
    }

subscribe to that Data

KnowledgeBaseAdminComponent

import { Component, OnInit } from '@angular/core';
import { KnowledgeBaseService } from '../../../services/knowledge-base.service';
import { WikiModel } from '../../../../models/wikiItems.model';
import { map, take } from 'rxjs/operators';
import {keyframes} from '@angular/animations';

@Component({
  selector: 'app-knwoledge-center-admin',
  templateUrl: './knowledge-base-admin.component.html',
  styleUrls: ['./knowledge-base-admin.component.scss']
})
export class KnowledgeBaseAdminComponent implements OnInit {

  wikiList: WikiModel[] = [];
  displayDialog: boolean = false;
  editItem: WikiModel = null;

  constructor(private knowledgebaseService: KnowledgeBaseService) {

  }

  ngOnInit() {
    this.getwikiItems()
  }

  getwikiItems(): void {
    this.knowledgebaseService.getwikiList().subscribe(
      data => {
        this.wikiList = data
      },
      err => console.error(err),
      () => console.log('Wiki Items Geladen')
    );
    console.log(this.wikiList)
  }

  showDialogToAdd() {
    this.displayDialog = true;

  }  showDialogToEdit() {
    this.displayDialog = true;
  }
}

WikiModel

export class WikiModel {
  title: string;
  text: string;
  keyWords: string;

}

Template

<div class="section section-wiki-admin-head">
  <h1 class="h-centered">Begriffsdatenbank</h1>
</div>
<div class="section section-wiki-admin-table">
  <div class="wiki-articles-table-container">
    <p-table [value]="wikiList">
       <ng-template pTemplate="header">
         <tr>
           <th>Begriff</th>
           <th>Beschreibung</th>
           <th>Schlagworte</th>
         </tr>
       </ng-template>
       <ng-template pTemplate="body" *ngFor="let wikiItems of wikiList">
         <tr>
           <td>{{wikiItems.title}}</td>
           <td>{{wikiItems.text}}</td>
           <td>{{wikiItems.keyWords}}</td>
         </tr>
       </ng-template>
     </p-table>
  </div>
</div>
<div class="section section-wiki-admin-footer">
  <div class="wiki-articles-table-toolbar">
    <button pButton id="wiki-a-new" class="ui-button-success wiki-a-footer-btn" type="button" icon="fa fa-plus" (click)="showDialogToAdd()" label="Neu"></button>
    <button pButton id="wiki-a-edit" class="ui-button-info wiki-a-footer-btn" type="button" icon="fa fa-edit"  (click)="showDialogToEdit()" label="Bearbeiten"></button>
    <button pButton class="ui-button-danger wiki-a-footer-btn"  type="button" icon="fa fa-trash" label="Löschen"></button>
  </div>
</div>
<p-dialog [header]="editItem && editItem? 'Bearbeiten' : 'Hinzufügen'" [(visible)]="displayDialog" [responsive]="true" showEffect="fade" [modal]="true" [width]="600">
  <div class="ui-g ui-fluid">

    <div class="ui-g-12">
      <div class="ui-g-4">
        <label for="wikiTitle">Titel</label>
      </div>
      <div class="ui-g-8">
        <input pInputText id="wikiTitle" />
      </div>
    </div>
    <div class="ui-g-12">
      <div class="ui-g-4">
        <label for="wikiText">Wiki Text</label>
      </div>
      <div class="ui-g-8">
          <textarea id="wikiText" [rows]="5" [cols]="35" pInputTextarea ></textarea>
      </div>
    </div>
<!-- TODO: change  textfield to P-chips -->
    <div class="ui-g-12">
      <div class="ui-g-4">
        <label for="wikikeywords">Schlagwörter</label>
      </div>
      <div class="ui-g-8">
        <input pInputText id="wikikeywords" />
      </div>
    </div>
  </div>
</p-dialog>

Error

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

The Data from the API looks like:

{
  "error": null,
  "status": 200,
  "result": [
    {
      "_key": "338330",
      "_id": "knowbaseItems/338330",
      "_rev": "XIQvCoG--",
      "title": "Test Eintrag",
      "text": "Lalala",
      "keyWords": [
        "test"
      ]
    },
    {
      "_key": "341705",
      "_id": "knowbaseItems/341705",
      "_rev": "XIHSQhy--",
      "title": "Personalpronomen",
      "text": "Fahren Schlitten",
      "keyWords": [
        "ich",
        "du",
        "er"
      ]
    }
  ],
  "code": "200"
}

Upvotes: 11

Views: 51907

Answers (4)

Ansh Shar
Ansh Shar

Reputation: 1

Look careful with your data coming from your api. If you use model class only those elements define in model class access.so make your you add data.result and then pass into another object

For e.g this.wikiList = data.result In html ngFor = "let wikilist of wikiList"

Upvotes: 0

Adesegun Koiki
Adesegun Koiki

Reputation: 71

You can also do the below:

getwikiList() {
return this.http.get(this.wikiApiUrl + "/list")
        .pipe(map((data: any) => data.result || [];
            }), catchError(error => {
            return throwError('Its a Trap!')
          })
        );

It worked for me

Upvotes: 2

Muhammed Albarmavi
Muhammed Albarmavi

Reputation: 24424

In your service map operator must return data.result

getwikiList() {
 return this.http.get(this.wikiApiUrl + "/list")
            .pipe(map((data: any) => data.result ), 
                  catchError(error => { return throwError('Its a Trap!')})
            );
}

Just update p-table like this

<p-table  [value]="wikiList">
       <ng-template pTemplate="header">
         <tr>
           <th>Begriff</th>
           <th>Beschreibung</th>
           <th>Schlagworte</th>
         </tr>
       </ng-template>
       <ng-template pTemplate="body" let-wikiList>
         <tr>
           <td>{{wikiList.title}}</td>
           <td>{{wikiList.text}}</td>
           <td>{{wikiList.keyWords}}</td>
         </tr>
       </ng-template>
     </p-table>

stackblitz example 🚀

Upvotes: 13

DeborahK
DeborahK

Reputation: 60528

Keep in mind that Http is asynchronous. That means with this code:

  getwikiItems(): void {
    this.knowledgebaseService.getwikiList().subscribe(
      data => {
        this.wikiList = data
      },
      err => console.error(err),
      () => console.log('Wiki Items Geladen')
    );
    console.log(this.wikiList)  // <-- ALWAYS UNDEFINED!!
  }

The last console.log line will always be undefined.

The flow is as follows:

1) The getwikiList().subscribe is called.

2) The Http Get request is executed.

3) The getwikiList() method returns.

4) Your console.log is executed and the value is undefined at this point.

5) A response is received from the Get request.

6) The method defined within the subscribe method is notified and the data is provided and set to the this.wikilist.

So it is only after step 6 that you have the data.

If you want to see your values, you need to move your logging within the subscribe as shown below:

  getwikiItems(): void {
    this.knowledgebaseService.getwikiList().subscribe(
      data => {
        this.wikiList = data;
        console.log(this.wikiList); // <-- here instead
      },
      err => console.error(err),
      () => console.log('Wiki Items Geladen')
    );
  }

Upvotes: 4

Related Questions