5

I am trying to get a uuid from the URL (which looks like https://something.com/card?id=where uuid goes) and then use that uuid to get a http get request.

Right now I have my app.component.ts looks like:

private cardUuid: string;

constructor(private service: AppService,
            private route: ActivatedRoute){
            let sub = this.route.params.subscribe((params: Params) => {
                  this.cardUuid = params['id'];
                  console.log(this.cardUuid)
                })

}


ngOnInit(){
  this.service.browserUuid = 'http://address/cards?uuid=' + this.sub.cardUuid;
    console.log(this.sub.cardUuid)

}

My console logs are coming back as undefined. I am wondering why that is the case? Is the method for getting the uuid wrong or is the call timing wrong?

Any help/tips/suggestions would be much appreciated.

Update: after a suggestion from @Alexander Staroselsky, I restructured my method of calling the uuid from the url per angular.io docs.

app.component.ts:

card: Card = {};

ngOnInit() {
 this.route.paramMap
  .switchMap((params: ParamMap) =>
    this.service.fetchCardUuid(+params.get('id')))
  .subscribe(
    card => {
      this.card = card;
      this.getVenueUuid(this.card);
    });
}

app-service.ts:

public UuidUrl = 'http://websiteaddress/cards?uuid='

constructor(private http: Http){}


private extractData(res:Response) {
  let body = res.json();
  return body || [];
}

fetchCardUuid(id: number) {
  return this.http.get(this.UuidUrl + id)
    .map(this.extractData)
}

However I am still not getting the app to load properly using the Uuid that is being fetched from the Url. In the console network is showing a get request of card?uuid=0. Again, any help would be much appreciated.

Bugs
  • 4,491
  • 9
  • 32
  • 41
Brian Stanley
  • 2,078
  • 5
  • 24
  • 43
  • The url pattern `http://address/cards?uuid=` is using `queryParams`, not `params`. You need to use `this.route.queryParamMap` instead of `this.route.paramMap`. `paramMap` will not have any values in it based on how the url is set up. – Alexander Staroselsky Jul 12 '17 at 15:15
  • This worked! As I am sure you are aware now, my understanding of queryParam versus param is lacking to say the least. Apologies for that. But that is pulling the id from the URL now. THANK YOU! – Brian Stanley Jul 12 '17 at 15:29
  • Please post solutions as answers not as updates to the question. This is to avoid confusion. Thank you. – Bugs Jul 12 '17 at 15:35
  • This [answer](https://stackoverflow.com/questions/30967822/when-do-i-use-path-params-vs-query-params-in-a-restful-api) has a good description of `params` vs `queryParams` in the context of general RESTful API applications. My original answer had queryParams referenced. Glad to hear it worked out! Please mark the answer that help you achieve the solution. – Alexander Staroselsky Jul 12 '17 at 15:39

2 Answers2

9

The format for the URL you provided is utilitizing query params (queryParams) rather than route params.

Update:

params would be used to retrieve a route parameter such as id in the following routing configuration (the :id in 'hero/:id'):

queryParams would be used to retrieve query params from a url pattern such as your https://something.com/card?id=. The identifier would be id, the part after ? and before the =.

{ path: 'hero/:id', component: HeroDetailComponent }

You can retrieve the query params in a similar way to this.route.params.subscribe() using this.route.queryParams.subscribe() like this:

constructor(
    private service: AppService, 
    private route: ActivatedRoute) {}

ngOnInit() {
    let sub = 
        this.route.queryParams
          .subscribe((queryParams: Params) => {
            this.cardUuid = queryParams['id'];
            console.log(this.cardUuid);

            this.service.browserUuid = 'http://address/cards?uuid=' + this.cardUuid;
          });


}

UPDATE:

Depending on the version of Angular (4+) you are using, you need access query params via an observable on ActivatedRoute called queryParamMap:

queryParamMap
An Observable that contains a map of the query parameters available to all routes. The map supports retrieving single and multiple values from the query parameter.

this.route.queryParamMap
    .subscribe((queryParams: QueryParamMap)) => {
        this.cardUuidt = queryParams.get('id');
        console.log(this.cardUuidt);

        this.service.browserUuid = 'http://address/cards?uuid=' + this.cardUuid;
});

Update:

One potential issue that could be causing issues is this.sub.cardUuid in ngOnInit(). You are defining a variable sub representing the Observable that is local to scope of the constructor. It would not be accessible in ngOnInit(). If this.sub is attempting to refer to the sub in constructor, that subscription would not have route params like cardUuid directly available. this.sub would come back undefined and this.sub.cardUuid would also in turn come back undefined. Also, you can't count on ngOnInit being executed after subscribe() has executed, so the resolved cardUuid from params may simply not be available.

Here is a plunker of the official Angular router live example. If you look at file app/hero-detail.component.ts and review the notes and the console statements when clicking into a hero detail component/view, you'll the undefined errors from trying to log this.sub and this.sub.uuid.

Hopefully that helps!

Alexander Staroselsky
  • 37,209
  • 15
  • 79
  • 91
  • That does help. You got me in the right direction. I am still getting an undefined it first runs the function but then it comes back with the value the second time. Progress! – Brian Stanley Jul 11 '17 at 02:18
  • Can you please clarify "the second time"? Could you also clarify what `this.sub` is referring to? See my updated answer. – Alexander Staroselsky Jul 11 '17 at 14:25
  • Apologies for the delay. When watching the console as the page loads, the console.log(this.cardUuid) returns undefined and then returns with the correct Uuid after a few moments later. I'm assuming that because it is located in ngOnInit() that it runs twice? – Brian Stanley Jul 12 '17 at 13:15
  • `ngOnInit()` and `contructor()` only run once when the component is instantiated, in this case when a hero is selected from the main view of the sample application. `ngOnInit()` and `contructor()` are effectively doing the same thing here just retrieving the values in different ways. – Alexander Staroselsky Jul 12 '17 at 15:13
  • Thanks I needed `this.route.paramMap`. Your Plunker example works great for me. – Melroy van den Berg Mar 30 '18 at 22:39
6

With the help of @AlexanderStaroselsky and @Angular docs, a solution was found.

My final ngOnInt() in app.component.ts looks like this:

ngOnInit() {
  this.route.queryParamMap
    .switchMap((params: Params) =>
      this.service.fetchCardUuid(params.get('id')))
    .subscribe(
      card => {
        this.card = card;
        this.getVenueUuid(this.card);
      });
}

This solution effectively gets the id from the Url and sends that id into a my service to make a get request. Again, cred goes to @AlexanderStaroselsky for the solution.

marcolz
  • 2,880
  • 2
  • 23
  • 28
Brian Stanley
  • 2,078
  • 5
  • 24
  • 43