25

I could use some advice how to approach this problem I'm facing. To explain this best possible for you I have created a main component:

@Component({
selector: 'main-component',
providers: [...FORM_PROVIDERS, MainService, MainQuoteComponent],
directives: [...ROUTER_DIRECTIVES, CORE_DIRECTIVES, RouterOutlet, MainQuoteComponent ],
styles: [`
    agent {
        display: block;
    }
`],
pipes: [],
template: `
   **Html hidden**
  `,
  bindings: [MainService],
})

@RouteConfig([
    { path: '/', name: 'Main', component: MainMenuComponent, useAsDefault: true },
    { path: '/passenger', name: 'Passenger', component: PassengerComponent },
])

@Injectable()
export class MainComponent {

bookingNumber: string;
reservation: Reservation;
profile: any;

constructor(params: RouteParams, public mainService: MainService) {

    this.bookingNumber = params.get("id");

     this.mainService.getReservation(this.bookingNumber).subscribe((reservation) => {

        this.reservation = reservation;
    });

    this.profile = this.mainService.getUserDetails();

} 

}

This component retreive a booking from the api and save it in the reservation object you see (It has a type of Reservation which is a class that looks like this)

export class Reservation {

constructor(
    public Id: number,
    public BookingNumber: string,
    public OutboundDate: Date,
    public ReturnDate: Date,
    public Route: string,
    public ReturnRoute: string,
    public Passengers: string,
    public Pet: string,
    public VehicleType: string,
    public PassengersList: Array<Passengers>

) { }
}

When I click the button Passenger, It will redirect to the passenger page Main/passenger, but here I need to send the reservation object (the whole one) or just the PassengerList (the array).

Do any know if its possible to do this with route params or with the router-outlet? Any suggestions?

Mandersen
  • 805
  • 3
  • 14
  • 22

1 Answers1

35

Just use a shared service and add it to the providers: [...] of the parent component.

Simple service class

@Injectable()
export class ReservationService {
  reservation:Reservation;
}

In parent add it to the providers and inject it in the constructor

@Component({...
   providers: [ReservationService]
export class Parent {
  constructor(private reservationService:ReservationService) {}

  someFunction() {
    reservationService.reservation = someValue;
  }
}

In the child component only inject it (don't add to providers)

@Component({...
  providers: []
export class Passenger {
  constructor(private reservationService:ReservationService) {
    console.log(reservationService.reservation);
  }

  someFunction() { 
    reservationService.reservation = someValue;
  }
}

update

bootstrap() is the common ancestor of everything and a valid option. It depends on what your exact requirements are. If you provide it at a component, then this component becomes the root of the tree that shares a single instance. This way you can specify the scope of a service. If the scope should be "your entire application" then provide it in bootstrap() or the root component. The Angular2 style guide encourages to favor providers of the root component over bootstrap(). The result will be the same though. If you just want to communicate between a component A and other components that are added to its <router-outlet> then it would make sense to limit the scope to this component A.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thsnks for your Quick reply.. Will look at it in the evening. – Mandersen Feb 18 '16 at 16:00
  • After 2 hours I finally nailed it :) the reservation was undefined, but fixed that by calling the method that maps the reservation object to the object in the service before using routerlink to passengerComponent. Thanks. – Mandersen Feb 19 '16 at 00:05
  • I am getting no providers for service error, if i don't pass the providers in the child component – user2180794 Jun 01 '16 at 03:33
  • Adding the service to providers in the child breaks the whole service concept because parent and child get different service instances. Hard to tell without seeing a full example. You still need to import the service where the chils component is defined. – Günter Zöchbauer Jun 01 '16 at 03:41
  • I think I am confusing the parent-child concept.. how do i make the component child of another ? – user2180794 Jun 01 '16 at 03:56
  • For using a service to communicate the component that does **not** have the service in `providers: []` needs to be added to the DOM somewhere within the component that **does have** the service in `providers: []`. If the "child" is added by the router to a `` of the "parent" (or any descendant) than this is enough already. DI looks from a component that has a constructor parameter upwards towards the root component (and then `bootstrap(...)` to find a provider. It then returns the instance from the first provider it found this way. – Günter Zöchbauer Jun 01 '16 at 04:05
  • Any downside bootstrapping this shared service at the root? in the bootstarp.ts file – user2180794 Jun 01 '16 at 05:09
  • I updated my answer because it was too long for a comment. – Günter Zöchbauer Jun 01 '16 at 05:12
  • I have made an array in the service and I'm trying to switch between 2 pages (both child of the same parent) but for some reason, the array inside of the service is empty when I change pages. Why is this? – FlorisdG Mar 24 '17 at 12:14
  • Sorry, hard to tell. Can you please create a new question that shows your code. The service, how you update the value, how you try to get the value in the components. – Günter Zöchbauer Mar 24 '17 at 12:16
  • 1
    Question can be found here: [link](http://stackoverflow.com/questions/43001080/angular-2-passing-objects-when-routing) – FlorisdG Mar 24 '17 at 13:45