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

4

11

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"
}
Venomous answered 17/7, 2018 at 19:59 Comment(1)
Please post all the template part.Polysyllabic
T
13

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 🚀

Teak answered 17/7, 2018 at 20:11 Comment(5)
@Venomous did you check the answer I have updated return the data.resultTeak
can you give me wikiApiUrl ?? @VenomousTeak
yep that erased that Error but my table is still empty.. ;/ my console Output looks like this now.. knowledge-base-admin.component.ts:34 [] length : 0 proto : Array(0) concat : ƒ concat() constructor : ƒ Array() copyWithin : ƒ copyWithin() entries : ƒ entries() every : ƒ every() fillVenomous
its a local API..that GET data from an external ArangoDB Server the API route looks like: localhost:3100/knowledge-base/list this URL gives a Full list of all Stored Data.. Output like: {"error":null,"status":200,"result":[{"key":"341705","_id":"knowbaseItems/341705","_rev":"_XIHSQhy--","title":"Personalpronomen","text":"Fahren Schlitten","keyWords":["ich","du","er"]}],"code":"200"}Venomous
@Venomous I have update the answer hope I help here :) , check stackblitz exampleTeak
L
4

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')
    );
  }
Lindahl answered 17/7, 2018 at 20:47 Comment(0)
A
2

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

Azikiwe answered 4/5, 2020 at 11:56 Comment(0)
K
0

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"

Kimikokimitri answered 8/6, 2022 at 9:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.