Reusing parameters among Angular components

162 Views Asked by At

When I'm sharing data among components should I call that data only once and provide it as @Input() or should I call that data again on every component's cycle?

For example, I have the following components in one page:

<game-info [id]="params?.id"></game-info>
<game-leaderboard [uid]="auth" [id]="params?.id"></game-leaderboard>
<game-progress [uid]="auth" [id]="params?.id"></game-progress>

Where I get the id from the ActivatedRoute and the uid from my authentication service. In some cases, I'm also passing a data input for multiple components in the same page.

One problem I face is that, sometimes, I'm passing data to many children components and it was harder to debug. For example:

game.component.html

<game-details [data]="data"></game-details>
<game-progress [data]="data"></game-progress>

Then, on details.component.html, I'd pass data as an input to another component - and so on. It became a really long chain:

<game-info [data]="data"></game-info>
<game-players [id]="(data | async)?.$key></game-players>

Is it a proper approach? Or would it be better to get those parameters inside of every component?

Another issue, for example, sometimes I need to get the an async parameter (e.g. uid from an Observable) during onInit but it didn't receive it yet. So, I was wondering if I should just call those parameters straight in the component instead of passing them as an input.

PS. I'm not sure if this is off-topic. If so, please feel free to remove it.

3

There are 3 best solutions below

0
On BEST ANSWER

Nothing wrong with that approach. Actually, this is 1 of the recommended ways nowadays where your top-level 'smart' components would gather the data and then inject that data to your 'presentational' aka 'view' aka 'dumb' components. Note that data also flows the other way around: all Events are emitted upwards, where they are handled by the containing 'smart' component. See here for a good (better) explanation.

I must say this approach has been working very well for me: code is clean (clear responsibilities, reusability and testability of presentational components...) although I must admit I share your concern that it might become a bit tedious when you have quite a lot of nested components.

2
On

A common approach would be using it as a Injectable service.

For its benefits, as it says:

The component can create the dependency, typically using the new operator. The component can look up the dependency, by referring to a global variable. The component can have the dependency passed to it where it is needed.

For angular 1, check https://docs.angularjs.org/guide/di

For angular 2, check the first answer in What's the best way to inject one service into another in angular 2 (Beta)?

1
On

It is hard to answer the question since I am not sure exactly what you are trying to achieve but it might be worth looking into services. Services will have one shared space for the components under the component it is declared under(example the app.component or even app.mudule). Then you can pass the new parameters to other components through the service. That would be the proper way of having a shared state and you can pass through many components by just injecting the service.