Request loop in Angularjs 2

Asked

Viewed 419 times

3

I am new to the use of Angularjs and decided to study based on a work project.

My problem is this:

I am building a base project using Angularjs 2 to consume data from Wordpress (WP) through the REST API of WP.

In this API I seek a post from WP (custom post called news) and I need to get the image highlighted in this post, only JSON does not return the image URL, it returns the link to the json with the media information (information that contains the image data) and the identifier of that media.

Following the tutorial of Angularjs 2, I created a news service to get the data on API of WP (below the codes) and also a service for media. In the news Detail I consume the data generated by the news service and expose them in the view, but to get the image I have to consume the data generated by the media service, through the identifier that is in the json news, then my problem arises.

The solution I imagined was the most obvious in my point of view, to make a method in news Detail that through the media identifier I took this data, it works, but in doing so, calling this method in the view, it goes into request loop. I then imagined doing this in the Detail component itself of news, but there the news object is undefined, so I do not have this identifier to make the request.

I imagine it’s a very simple solution, but I have no idea how to solve, it’s been several days that I’m stuck in it.

What would be the best solution?

Codes

noticia.service.ts

import {Noticia} from "./noticia";
import {Injectable} from "@angular/core";
import {Http, Response, Headers, RequestOptions} from "@angular/http";
import {Observable} from "rxjs/Observable";
import {AppConstants} from ".././app-constants";
import "rxjs/Rx";

@Injectable()
export class NoticiaService {

    constructor(private _http: Http) { }

    private _apiUrl: string = AppConstants.API_URL;

    getNoticias() {
        return this._http.get(this._apiUrl + "noticias")
            .map(res => res.json())
            .catch(this.throwError);
    }

    getNoticia(id: number) {
        return this._http.get(this._apiUrl + "noticias/:id".replace(":id", id.toString()))
        .map(res => res.json())
        .catch(this.throwError);
    }

    private throwError(response) {
        return Observable.throw(response.json().error || "Server error")
    }

}

media.service.ts

import {Media} from "./media";
import {Injectable} from "@angular/core";
import {Http, Response, Headers, RequestOptions} from "@angular/http";
import {Observable} from "rxjs/Observable";
import {AppConstants} from ".././app-constants";
import "rxjs/Rx";

@Injectable()
export class MediaService {

    public medias: Array<Media>;
    constructor(private _http: Http) { }

    private _apiUrl: string = AppConstants.API_URL;

    getMedias() {
        return this._http.get(this._apiUrl + "media")
            .map(res => res.json())
            .catch(this.throwError);
    }

    getMedia(id: number) {
        return this._http.get(this._apiUrl + "media/:id".replace(":id", id.toString()))
                .map(res => res.json())
                .catch(this.throwError);
   }

    private throwError(response) {
       return Observable.throw(response.json().error || "Server     error")
    }

}

noticia-Detail.component.ts

    import {Component, OnInit} from "@angular/core";
    import {NoticiaService} from "./noticia-service";
    import {MediaService} from "../medias/media-service";
    import {RouteParams} from '@angular/router-deprecated';

    import {Noticia} from "./noticia";
    import {Media} from "../medias/media";
    import {AppConstants} from ".././app-constants";



    @Component({
        templateUrl: "app/view/noticias/noticia-detail.html",
    })

    export class NoticiaDetailComponent implements OnInit {

        public noticia: Noticia;
        public imagemDestaque: Media;
        public constantes: AppConstants = AppConstants;

        constructor(private _routeParams: RouteParams, private _noticiaService: NoticiaService, private _mediaService: MediaService) { }

    ngOnInit() {
        let id = <number><any>this._routeParams.get("id");
        this._noticiaService.getNoticia(id).subscribe(data => this.noticia = data, error => console.log(error));
    }

    public getImagemDestaque(id: number) {
        this._mediaService.getMedia(id).subscribe(data => this.imagemDestaque = data, error => console.log(error));
    }

}

noticia-Detail.html

<div *ngIf="noticia" class="col-md-12">
    <article>
        <section>
            <header>
                <h3>{{noticia.title.rendered}}</h3>
                <span class="text-muted">Publicado em {{constantes.formatarDataWP(noticia.modified)}}</span>
            </header>
            {{getImagemDestaque(noticia.featured_media)}}
                        <p *ngIf="imagemDestaque">
                            <img src="{{imagemDestaque.media_details.sizes.full.source_url}}" alt="{{imagemDestaque.title.rendered}}" title="{{imagemDestaque.title.rendered}}"/>
                        </p>
        </section>
    </article>
</div>

news.json

{
  "id": 116,
  "date": "2016-06-01T10:55:27",
  "date_gmt": "2016-06-01T13:55:27",
  "guid": {
    "rendered": "http://localhost/gerenciadorWP/?post_type=noticias&#038;p=116"
  },
  "modified": "2016-06-02T16:51:28",
  "modified_gmt": "2016-06-02T19:51:28",
  "slug": "mais-uma-noticia",
  "type": "noticias",
  "link": "http://localhost/gerenciadorWP/en/blog/noticias/mais-uma-noticia/",
  "title": {
    "rendered": "(Português do Brasil) Mais uma noticia"
  },
  "content": {
    "rendered": ""
  },
  "excerpt": {
    "rendered": ""
  },
  "featured_media": 127,
  "comment_status": "open",
  "ping_status": "closed",
  "tags": [],
  "acf": {
    "corpo": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
    "resumo": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut a",
    "chapeu": "Chapéu (ante-título)",
    "subtitulo": "Subtítulo",
    "origem": "",
    "autor": "Jeffersson",
    "documentos": [
      123
    ],
    "fotos": [
      105
    ]
  },
  "_links": {
    "self": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/noticias/116"
      }
    ],
    "collection": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/noticias"
      }
    ],
    "about": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/types/noticias"
      }
    ],
    "replies": [
      {
        "embeddable": true,
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/comments?post=116"
      }
    ],
    "version-history": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/noticias/116/revisions"
      }
    ],
    "wp:featuredmedia": [
      {
        "embeddable": true,
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/media/127"
      }
    ],
    "wp:attachment": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/media?parent=116"
      }
    ],
    "wp:term": [
      {
        "taxonomy": "post_tag",
        "embeddable": true,
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/tags?post=116"
      }
    ],
    "curies": [
      {
        "name": "wp",
        "href": "https://api.w.org/{rel}",
        "templated": true
      }
    ]
  }
}

media.json

{
  "id": 127,
  "date": "2016-06-02T16:51:16",
  "date_gmt": "2016-06-02T19:51:16",
  "guid": {
    "rendered": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it.jpeg"
  },
  "modified": "2016-06-02T16:51:16",
  "modified_gmt": "2016-06-02T19:51:16",
  "slug": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it",
  "type": "attachment",
  "link": "http://localhost/gerenciadorWP/en/blog/noticias/mais-uma-noticia/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it/",
  "title": {
    "rendered": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it"
  },
  "author": 1,
  "comment_status": "open",
  "ping_status": "closed",
  "alt_text": "",
  "caption": "",
  "description": "",
  "media_type": "image",
  "mime_type": "image/jpeg",
  "media_details": {
    "width": 2560,
    "height": 1600,
    "file": "2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it.jpeg",
    "sizes": {
      "thumbnail": {
        "file": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-150x150.jpeg",
        "width": 150,
        "height": 150,
        "mime_type": "image/jpeg",
        "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-150x150.jpeg"
      },
      "medium": {
        "file": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-300x188.jpeg",
        "width": 300,
        "height": 188,
        "mime_type": "image/jpeg",
        "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-300x188.jpeg"
      },
      "medium_large": {
        "file": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-768x480.jpeg",
        "width": 768,
        "height": 480,
        "mime_type": "image/jpeg",
        "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-768x480.jpeg"
      },
      "large": {
        "file": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-1024x640.jpeg",
        "width": 1024,
        "height": 640,
        "mime_type": "image/jpeg",
        "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-1024x640.jpeg"
      },
      "post-thumbnail": {
        "file": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-1200x750.jpeg",
        "width": 1200,
        "height": 750,
        "mime_type": "image/jpeg",
        "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it-1200x750.jpeg"
      },
      "full": {
        "file": "2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it.jpeg",
        "width": 2560,
        "height": 1600,
        "mime_type": "image/jpeg",
        "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it.jpeg"
      }
    },
    "image_meta": {
      "aperture": "0",
      "credit": "",
      "camera": "",
      "caption": "",
      "created_timestamp": "0",
      "copyright": "",
      "focal_length": "0",
      "iso": "0",
      "shutter_speed": "0",
      "title": "",
      "orientation": "1",
      "keywords": []
    }
  },
  "post": 116,
  "source_url": "http://localhost/gerenciadorWP/wp-content/uploads/2016/06/2014_batman_arkham_knight-wide-batman-arkham-knight-has-shadow-of-mordor-s-combat-affected-it.jpeg",
  "_links": {
    "self": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/media/127"
      }
    ],
    "collection": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/media"
      }
    ],
    "about": [
      {
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/types/attachment"
      }
    ],
    "author": [
      {
        "embeddable": true,
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/users/1"
      }
    ],
    "replies": [
      {
        "embeddable": true,
        "href": "http://localhost/gerenciadorWP/en/wp-json/wp/v2/comments?post=127"
      }
    ]
  }
}

2 answers

1


With the help of Nicolas Takashi, that told me to study about Lifecycle Hooks in Angularjs 2 I discovered the problem of multiple requests. So I was able to figure out where in the Lifecycle of the Component the object news was set and there I made the call from the media service to retrieve the image data. After the image is set I canceled the service subscription to have no problems with Memory Leak besides using ngOnDestroy hook to release all services.

1

Have you ever used a debug method to see which values are arriving in the picture variable? Use batarang to debug the js so you can check if the json is being loaded correctly. I believe it must be something, probably some detail. Or some internal error of angular, finally without debugging has no way, in terms of code I saw nothing wrong.

Try to run straight to see if it will loop:

import {Component, OnInit} from "@angular/core";
    import {NoticiaService} from "./noticia-service";
    import {MediaService} from "../medias/media-service";
    import {RouteParams} from '@angular/router-deprecated';

    import {Noticia} from "./noticia";
    import {Media} from "../medias/media";
    import {AppConstants} from ".././app-constants";



    @Component({
        templateUrl: "app/view/noticias/noticia-detail.html",
    })

    export class NoticiaDetailComponent implements OnInit {

        public noticia: Noticia;
        public imagemDestaque: Media;
        public constantes: AppConstants = AppConstants;

        constructor(private _routeParams: RouteParams, private _noticiaService: NoticiaService, private _mediaService: MediaService) { }

 public getImagemDestaque(id: number) {
        this._mediaService.getMedia(id).subscribe(data => this.imagemDestaque = data, error => console.log(error));
    }

    ngOnInit() {
        let id = <number><any>this._routeParams.get("id");
        this._noticiaService.getNoticia(id).subscribe(data => this.noticia = data, error => console.log(error));

        this.getImagemDestaque(noticia.featured_media);
    }



}
  • The values arrive normal in the variable imageDestaque, but the thing is that the view keeps calling in loop the getImagemDestaque method, what I’m not getting.

  • I do not understand much of angular 2, but already tried to run direct by js , I will put in question

  • It does not work, because in ngOnInit the object news is not defined yet.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.