简体   繁体   中英

Angular2 RC1: Passing data down to components

I guess, this issue has been discussed before, both for the new RC router and the deprecated router. The favored solution seemed to be using services for passing data down to components activated by router-outlet.

However, the more I think about it, the more I find myself in a hell of concurreny, observables and eventemitters. Please consider the following scenario:

A route is called like this: "/car/123/motor/4/sparkcoil"

which means: get the data for the spark coil for the motor with ID 4, which, in turn, is part of a car with ID 123.

So, there are 3 components with nested routes, the "car" component, the "motor" component and the "spark coil" component. The first components have a router-outlet, in which the child component is rendered. Not too difficult, so far.

Let's make some assumptions:

1) In the "motor" component I need access to to the car data, and in the "spark coil" component, I need to have access to both the car data and the motor data.

2) The backend call to get a car would not contain data about all of the available motor types, because of the immense data volume. So car, motor and spark coil data have to be fetched in separate backend calls.

The first component that is activated is for the route "/car/123" is the car component. It has a service injected, that makes the backend call and returns an Observable, to which the components subscribes.

Then, the second route "/motor/4" is activated. I need to know about the car object fetched by the parent component. Later on, the "/sparkcoil" component is activated, which needs to know about the motor and the car, as well. Obviously there is not way to get it passed by an @Input decorator, right now. Frequent recommendations are: use a service. Alright, so I inject service X into both the car and the motor component. Here comes the pain. I have no satisfying solution for designing the service without finding myself in a concurrent hell of eventemitters or observables.

Idea 1:

The car and the motor component call a function on the service named fetchMotor(id) and fetchCar(id) which, in turn, trigger the next() method of a motorFetchedEventEmitter and carFetchedEventEmitter. The motor and the sparkcoil component subscribe to all of the EventEmitters to get informed about when the backend data have been fetched. However, I don't know if the components subscribe to the EventEmitter before or after they fire. If before, everything is fine, if after, I need to need to "replay" the emittals (see Observable.replay(...)). Since the service and their EventEmitters are instantiated only once, replaying the Observables means that I may get a lot of (irrelevant) events.

Idea 2:

I'll do it the other way round. The car and the motor component remain idle until the spark coil component is called. This component resolves all route segments, performs the respective backend calls and propagates the backend response via EventEmitters of a service to the "car" and "motor" component. I admit that this approach is quite counterproductive in regards to the new component routing as of RC1.

Possibly there is a better solution for this scenario, considering life cycle hooks. According to the docs, the OnActivate interface (see https://angular.io/docs/js/latest/api/router/OnActivate-interface.html ) says, that when onActivate returns a promise, all child components won't be activated until the promise resolves. I don't think that there is a similar functionality for routed components.

Does anyone have a notion how to solve this as elegantly as possible.

Thanks for your ideas in advance. I need to get a coffee! :-?

You shouldn't use EventEmitter in services. This was common practice for quite some time but EventEmitter should only be used for @Output() on components.

I think the whole problem is just a design problem about how you use observables and services (I don't say its an easy problem to solve).

Using BehaviorService might be an option to fix timing issues where services subscribe to observables after these emitted a value. With BehaviorService a new subscriber immediately gets the last emitted value passed.

Your question doesn't contain enough information for more detailed suggestions and seems a bit too broad for StackOverflow anyway. If you can break down your problem to single issues and create new questions for these it might be easier to make concrete suggestions about how to fix it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM