Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid argument for pipe 'AsyncPipe'

So i get this when i try to get my data from firebase

Invalid argument '{"-KCO4lKzEJPRq0QgkfHO":{"description":"teste","id":1457488598401,"resourceUrl":"tete","title":"test2"}}' for pipe 'AsyncPipe' in [listItems | async  in ArcListComponent@2:10]

ArcListComponent

import { Component, OnInit } from "angular2/core";
import { FirebaseService } from "../shared/firebase.service";
import { ArcItem } from "./arc-item.model";


@Component({
    selector: "arc-list",
    template: `
    <ul class="arc-list">
      <li *ngFor="#item of listItems | async " class="arc-item">
        <h3>{{ item.name}}</h3><a [href]="item.resourceUrl" target="_blank" class="btn btn-success pull-right"><span>Go</span></a>
        <hr>
        <blockquote>{{ item.description }}</blockquote>
        <hr>

      </li>
    </ul>
    `

})

export class ArcListComponent implements OnInit {
  listItems: string;

  constructor(private _firebaseService: FirebaseService) {}

  ngOnInit(): any {
    this._firebaseService.getResources().subscribe(
      resource => this.listItems = JSON.stringify(resource),
      error => console.log(error)
    );
  }

}

firebase_service

import { Injectable } from "angular2/core";
import { Http } from "angular2/http";
import "rxjs/Rx";

@Injectable()
export class FirebaseService {

  constructor(private _http: Http) {}

  setResource(id: number, title: string, description: string, resourceUrl: string) {
    const body = JSON.stringify({ id: id, title: title, description: description, resourceUrl: resourceUrl});

    return this._http
                     .post("https://######.firebaseio.com/resource.json", body)
                     .map(response => response.json());
  }

  getResources() {
    return this._http
                     .get("https://######.firebaseio.com/resource.json")
                     .map(response => response.json());
  }
}

I know i am trying to show my data the wrong way but i do not know how to fix this. any help appreciated.

like image 625
Petros Kyriakou Avatar asked Mar 09 '16 02:03

Petros Kyriakou


2 Answers

The async pipe expects an observable or a promise. http.get and map operator return observable, so you can set the returned object into the listItems property of your component. You don't need to subscribe in this case:

this.listItems = this._firebaseService.getResources();

Moreover the object, this element will "receive" must be an array to be able to use it within an ngFor. You service returns an object and not an array from Firebase. If you want to iterate over the keys of the object, you need to implement a custom pipe:

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push({key: key, value: value[key]);
    }
    return keys;
  }
}

and use it like this:

@Component({
  selector: "arc-list",
  template: `
  <ul class="arc-list">
    <li *ngFor="#item of listItems | async | keys" class="arc-item">
      <h3>{{ item.value.name}}</h3><a [href]="item.value.resourceUrl" target="_blank" class="btn btn-success pull-right"><span>Go</span></a>
      <hr>
      <blockquote>{{ item.value.description }}</blockquote>
      <hr>

    </li>
  </ul>
  `,
  pipes: [ KeysPipe ]
})

See this question for more details:

  • How to display json object using *ngFor
like image 128
Thierry Templier Avatar answered Nov 16 '22 04:11

Thierry Templier


async pipe works with observables and/or promises. It does subscription for you, so you just have to pass an observable without subscribing to it in your code:

  ngOnInit(): any {
    this.listItems = this._firebaseService.getResources()
  }
like image 39
Sasxa Avatar answered Nov 16 '22 04:11

Sasxa