0

I have two components in my application - MasterComponent and DetailsComponent

On clicking an option in MasterComponent, it is routed to DetailsComponent, also I need to pass some dynamic objects to DetailsComponent. As far as I understand there are few ways to achieve this

1] Using router params

I can't pass objects using router params, only strings because it needs to be reflected in the URL.

2] Using shared service

We can pass complex objects through a shared service but on reloading the page the data in the service is cleared. I need data to be persisted on page reload.

Is there any other way to pass dynamic complex data to routed Component? Any help is appreciated. Thanks.

Abhishek V
  • 12,488
  • 6
  • 51
  • 63

2 Answers2

2

I would use a shared service. Is really the best approach in my humble opinion.

Check this: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

The example there is very self explanatory! :D

The service works with listeners, so you subscribe to it. And when both components are subscribed to it the flow of data is consistent and fluid. I used this approach myself to communicate between my back end server and 3 components in my App.

My data flow is the following:

  1. Component A receives data from server. Stores it into an object and calls a method in a shared service passing this object.
  2. Component B listens to this method and receives the data passed from Component A to the shared service.
  3. Same approach with Component C.

Is this flow what you are looking for?

Update (saving data when reloading) :

Storing data options:

  1. LocalStorage
  2. Cookie
  3. Session

Links:

Hope it helped! Good coding!

Community
  • 1
  • 1
SrAxi
  • 19,787
  • 11
  • 46
  • 65
  • Thanks for the answer. As I mentioned in the question, if we use a shared service, data is cleared on reloading the page. Do you have any solution to this problem? – Abhishek V Apr 04 '17 at 14:06
  • @AbhishekV I am not reloading the page almost never, but when I do I repeat the process: 1. Get data from Server. 2. Pass it to rest of the Components through shared service. This helps me to have 1 Component that gathers the data from the Server and manages it, and then sends it to the DataTables component (for example). So, I just make 1 call to server and manage at its best the data. – SrAxi Apr 04 '17 at 14:08
  • @AbhishekV Just have a Component A to gather your data, manage it and put it into an object. And pass that object throughout all your App using a shared service. As soon as you get used to it will be your best friend when passing data from one component to another. – SrAxi Apr 04 '17 at 14:11
  • But what if the data is not coming from server, if user has submitted the data through from then how we can persist it? – Abhishek V Apr 04 '17 at 14:27
  • @AbhishekV Well, you can always pass data using `@Input()` but, when reload you lose it. So in the case that you want to maintain data when refreshing/reloading, you will need to store it: local json, cache, etc. I will update my answer with some useful links for this matter – SrAxi Apr 04 '17 at 14:32
  • Sure. Will look into those. Thanks – Abhishek V Apr 04 '17 at 14:37
  • @AbhishekV No problem! Think also that if you import well a service, you can use it anywhere in your app. So you can have a common service not folder wise but conceptual wise. For example, you can have a `UsersService` that manages all the components and data related to users. That means that you can put into communication all the components related to users, even though they are not *parent>Child* or are not under same folders... – SrAxi Apr 04 '17 at 14:52
0

You can do so using Resolve; say you need to get user infos from your database through one of your services and need to display it in your details-component.

Resolving route datas will enable you to fetch datas before activating the selected route.

In your route config:

{
  path: 'user/:id',
  component: 'UserDetailComponent',
  resolve: {
    userProfile: "UserProfileResolverService"
  }
}

Your UserProfileResolverService would be:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from "@angular/router";
import { User } from "path";
import { UserService } from "path to your service";

@Injectable()
export class UserProfileResolverService implements Resolve<any>{

  constructor(private userService: UserService) { }

  resolve(route: ActivatedRouteSnapshot){

    return this.userService.getUser(route.paramMap.get('id'))
        .toPromise()
        .then(res =>{
          return res.json().data as User[];
        });

  }

}

For way more infos about resolving route datas read the excellent article by Pascal Precht: https://blog.thoughtram.io/angular/2016/10/10/resolving-route-data-in-angular-2.html

t3__rry
  • 2,817
  • 2
  • 23
  • 38
  • Thanks for the answer. Is it possible to pass form data submitted in one component to another content through this method? – Abhishek V Apr 04 '17 at 14:44
  • To communicate between components use `Events` and `@Output()`: https://toddmotto.com/component-events-event-emitter-output-angular-2 – t3__rry Apr 04 '17 at 14:55
  • But `@Input` and `@Output` can be used only if one component is child of another component right. I don't think it can be used in case of routing – Abhishek V Apr 04 '17 at 14:58