2

Even though it seems like a common situation I haven't found a decent solution of how do I share a data from the parent to children routes.

Routes:

{
    path: ':id',
    component: DetailComponent,
    children: [
        { path: 'overview', component: OverviewComponent },
        { path: 'profile', component: ProfileComponent }
    ]
}

Service:

@Injectable()
export class Service {
    constructor(private http: Http) { }

    getModel(id: number): Observable<Profile> {
        // ajax request to the server using Http service
        // returns Profile model
    }
}

DetailComponent (parent):

@Component({
    moduleId: module.id,
    templateUrl: 'detail.component.html'
})
export class DetailComponent implements OnInit, OnDestroy {
    model: any = {}; // how do I share this with children components avoiding another ajax request?

    private paramSub: any;
    private modelId: number;

    constructor(
        private activeRoute: ActivatedRoute,
        private service: Service) { }

    ngOnInit(): void {
        this.paramSub = this.activeRoute.params.subscribe(params => {
            this.modelId = +params['id'];
            this.service.getModel(this.modelId).subscribe(model => this.model = model);
        });
    }

    ngOnDestroy(): void {
        this.paramSub.unsubscribe();
    }
}

OverviewComponent (child):

@Component({
    moduleId: module.id,
    templateUrl: 'overview.component.html'
})
export class OverviewComponent implements OnInit, OnDestroy {
    model: any = {};

    private paramSub: any;
    private modelId: number;

    constructor(
        private activeRoute: ActivatedRoute,
        private service: Service) { }

    ngOnInit(): void {
        this.paramSub = this.activeRoute.parent.params.subscribe(params => {
            this.modelId = +params['id'];
            // another request to the server which I need to prevent
            this.service.getModel(this.modelId).subscribe(model => this.model = model);
        });
    }

    ngOnDestroy(): void {
        this.paramSub.unsubscribe();
    }
}

As you can see the parent component receives a common data that needs to be passed to the children routes. If possible to cache this data in the Service can someone advice a proper way of achieving this and invalidating the cache? If all of this is not a good practice please suggest the proper way.

angular: 2.0.0-rc.6; router: 3.0.0-rc.2

Zabavsky
  • 13,340
  • 8
  • 54
  • 79
  • Usually a shared service is the best approach for this situation https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service – Günter Zöchbauer Sep 11 '16 at 13:48
  • Possible duplicate of [caching results with angular2 http service](http://stackoverflow.com/questions/34104277/caching-results-with-angular2-http-service) – Tiberiu Popescu Sep 11 '16 at 13:54
  • This is the right way of sharing a service, so you may want to look how to cache the http request : http://stackoverflow.com/questions/34104277/caching-results-with-angular2-http-service – Tiberiu Popescu Sep 11 '16 at 13:55
  • You're on the right track. Instead of calling `getModel` whenever you want the data, store the request in an Observable property and then subscribe to that. That way you only have to call getModel once and everything subscribed to the property will get the value. – spongessuck Sep 11 '16 at 14:59
  • 1
    Thanks everyone, [this answer](http://stackoverflow.com/a/36291681/1199711) helped me. I'm not sure whether to consider this as a duplicate since the question is more about the correct way rather than caching an http call. @GünterZöchbauer, feel free to close the question if you think it's a duplicate or perhaps you want to post an example of shared service approach? – Zabavsky Sep 11 '16 at 16:19

1 Answers1

0
import { Observable } from 'rxjs/Observable';
...

@Injectable()
export class Service {
    private model: Profile;
    constructor(private http: Http) { }

    getModel(id: number): Observable<Profile> {
        if (this.model) { 
            return Observable.of(this.model); 
        }

        // ajax request to the server using Http service
        // returns Profile model
        return http.get(...).map(res => this.model = res)
    }
}
yrunts
  • 153
  • 8