1

I have a service http which loads (and puts) data to/from API. In this case I need to get data from server and show them in template.

This is my code

export class RouteDetailComponent implements OnInit{
  public routeId:number;
  public route:Route;
  public actUrl: string;
ngOnInit() {
this.routeId = this.activateDroute.snapshot.params['id'];

let data;
this.httpService.getRoute(this.routeId)
    .subscribe(
        (response: Response) => {
            data = response.json().data;

            this.route = new Route(
                data.route_id,
                data.route_name,
                data.user_id,
                data.first_name+" "+data.last_name,
                data.tags,
                data.added,
                data.last_changed,
                data.geojson,
                data.visible,
                data.description,
                data.reviews,
                data.route_length.toPrecision(3)
            );
            console.log(this.route);
        },
        (error) => console.log(error)
    );
  }
}

The route object is just object storing information of route (Some constructor, method parsing input data etc).

In template I'm using route object like <h4>{{this.route.routeName}}</h4>. When I try to run this code I get many errors telling me Im trying to access property of undefined.

I think It's becouse subscribe is async event and html is rendered right after NgOnInit. However I do not know how to handle this. I would like to add some loading to the template before It's loaded from API and then show user that data.

Can anyone tell me how to do it, please?

3
  • yeah, you are right Angular is unaware of the existence of Route class data members during view initialization because you are instantiating it inside the subscribe which would be called once response arrives. my suggestion would be to go for setters and getters or wait for someone else to pitch in with a solution :) Commented Mar 11, 2018 at 13:07
  • Possible approach is to protect the view by ng-if condition(s) *ngIf="!!route" Commented Mar 11, 2018 at 13:09
  • @dhilt yea I got that idea too. But I wondered if there is some more elegant way to do it. Commented Mar 11, 2018 at 13:30

2 Answers 2

1

You don't need to use this.route in your template code, route is enough.

You can use the Elvis operator to make sure you don't run into undefined variable issues

<h4>{{route?.routeName}}</h4>

Or you can wrap all the template code in *ngIf

<div *ngIf="route!=null">
    <h4>{{route.routeName}}</h4>   
</div>
Sign up to request clarification or add additional context in comments.

Comments

0

One way you can handle this is that you can define your models like this to handle the data received.

class Route {
    //Type you can set here
    route_id: string ;
    route_name: string ;
    user_id: string ;
    first_name: string;
    last_name: string; 
    tags: string ;
    added: string ;
    last_changed: string ;
    geojson: string ;
    visible: string ;
    description: string ;
    reviews: string ;
    route_length: number ;

    constructor(obj?: any) {
        this.route_id =  (obj && obj.route_id) || '';
        this.route_name =  (obj && obj.route_name) || '';
        this.user_id =  (obj && obj.user_id) || '';
        this.first_name =  (obj && obj.first_name) || '';
        this.last_name =  (obj && obj.last_name) || '' 
        this.tags =  (obj && obj.tags) || '';
        this.added =  (obj && obj.added) || '';
        this.last_changed =  (obj && obj.last_changed) || '';
        this.geojson =  (obj && obj.geojson) || '';
        this.visible =  (obj && obj.visible) || '';
        this.description =  (obj && obj.description) || '';
        this.reviews =  (obj && obj.reviews) || '';
        this.route_length =  (obj && obj.route_length && obj.route_length.toPrecision) || 0;
    }
}
// With this type of model you don't have to worry about API data.
// It will handle everything and the component 
// won't break even if you are accessing any nested object.

export class RouteDetailComponent implements OnInit{
public routeId:number;
public route:Route = new Route(); //Here you need to initialize your route
public actUrl: string;
    ngOnInit() {
    this.routeId = this.activateDroute.snapshot.params['id'];

    let data;
    this.httpService.getRoute(this.routeId)
        .subscribe(
            (response: Response) => {
                data = response.json().data;

                //Here you can simply pass the response from API 
                //and you will get the data in proper format
                this.route = new Route(data); 
                console.log(this.route);
            },
            (error) => console.log(error)
        );
    }
}

So with this even if the API data has not arrived still it will be handled.

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.