0

I have an external API that returns a list. I have the following in service

load() {
    let headers = new Headers();
    headers.append("Authorization", Config.token);

    return this._http.get(Config.apiUrl + "grocery/list", {headers: headers})
        .map(res => res.json())
        .map(data => {
            let groceryList = [];
            data.list.forEach((grocery) => {
                groceryList.push(new Grocery(grocery._id, grocery.name));
            });
            return groceryList;
        })
        .catch(this.handleErrors);
}

I have the following code in component:

ngOnInit() {
    this._groceryService.load()
        .subscribe(loadedGroceries => {
            loadedGroceries.forEach((groceryObject) => {
                console.dir(groceryObject);
                this.groceryItems.unshift(groceryObject);
            });
        });

    // It works if I uncomment this. It will just render one item, still nothing from API
    // this.groceryItems.unshift(new Grocery('iuiu', 'jjjjj'));
}

If I uncomment the final line above it is rendering on the ListView. My ListView is templated away and look like below:

<GridLayout>
  <ListView [items]="groceryItems" class="small-spacing">
    <template let-item="item">
      <Label [text]="item.name" class="medium-spacing"></Label>
   </template>
  </ListView>
</GridLayout>

The API returns something like this:

{
  "success": true,
  "msg": "Lists found!",
  "list": [
    {
      "_id": "574a324a18cadad00665a7f3",
      "name": "Carrot",
      "userid": "57482f309ae6c358703066ca",
      "completed": 0,
      "__v": 0
    }
  ]
}
1
  • 1
    Hey Deepak, I’m not sure specifically what‘s going wrong here, but I’ve hit this sort of issue as well. You may want to consider switching over to an RxJS Observable for your list as well as the async pipe. That just seems to be the way Angular wants this sort of thing implemented, and I’ve had better luck with that approach. The Groceries repo’s “angular” branch has a sample implementation you can take a look at github.com/NativeScript/sample-Groceries/tree/angular. Commented May 31, 2016 at 17:08

2 Answers 2

2

You could add this line after you call the load method setTimeout(() => {this.cd.markForCheck();}, 0);. This will allow ListView to be update every time you are pushing new item to the array. I am attaching below some code snippets:

import {Component, Input, ChangeDetectionStrategy, ChangeDetectorRef} from "@angular/core"; import {Http, Headers, Response, ResponseOptions, HTTP_PROVIDERS} from "@angular/http"; import {Observable, BehaviorSubject} from "rxjs/Rx";

constructor(private _http: Http, private cd: ChangeDetectorRef){

         this.groceryItems=[];
    }



 ngOnInit() {
      this.groceryItems.push(new Grocery( '3','test', false, false));
      this.load()
            .subscribe(loadedGroceries => {
                loadedGroceries.forEach((groceryObject) => {
                    this.groceryItems.push(new Grocery( '3',groceryObject.name, false, false));
                    console.log(this.groceryItems.length);
                    console.log(groceryObject.name);
                });
                this.cd.markForCheck();
            });
  }
Sign up to request clarification or add additional context in comments.

3 Comments

Why do you think setTimeout() is needed for the call to cd.markForCheck()?
this.cd.markForCheck() is already to notify about changes. setTimeout() by itself also notifies about changes. This seems redundant, especially with default ChangeDetectionStrategy.
You are right. I tested my project ones again and it looks that this.cd.markForCheck() works correctly without setTimeout().
1

Just a hint

Using map instead of forEach() and push() should do the same but more concise:

load() {
    let headers = new Headers();
    headers.append("Authorization", Config.token);

    return this._http.get(Config.apiUrl + "grocery/list", {headers: headers})
        .map(res => res.json())
        .map(data => 
          data.list.map(grocery => new Grocery(grocery._id, grocery.name))
        )
        .catch(this.handleErrors);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.