Communicate Between Components Using Angular Dependency Injection

Isaac Mann
InstructorIsaac Mann
Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 5 years ago

Allow more than one child component of the same type. Allow child components to be placed within the views of other custom components

Instructor: [00:00] We have a new requirement for this compound toggle component. We need to support having multiple toggle-on and toggle-off child components inside of it, so let's see if that works. Looks like only one of the toggle-on and toggle-off components is actually being updated.

[00:15] We actually have another requirement as well. We've been handed this other component over here that contains its own toggle-on and toggle-off component. That should be able to be included here and receive its state from the toggle component. However, it looks like that's not updating either.

[00:39] One way to fix having multiple child components is to go into the toggle component.ts file here and change from content-child to content-children. Then you would get a query list of toggle-on components and you could iterate through those, but that wouldn't solve the problem with the other component.

[00:58] We're going to rewire the communication between the parts of this compound component to use dependency injection instead of content-child or content-children.

[01:06] First, let's take a look at the toggle-on component. Instead of having its own internal state, we will use the constructor to inject an instance of the parent toggle component. Then we can simply use the toggle component's state inside of this child toggle-on component, and we'll fix the imports here.

[01:37] Next, we'll do the same thing with the toggle-off component. We're injecting the parent toggle component and we're using the state from that component in our template here. The last child component is the toggle button component.

[01:52] Once again, we're replacing the inputs and outputs with a reference to the parent toggle component. In the template, we're using that parent toggle component state but we need to do something different in this on-click method here. All of this logic needs to be moved up to the parent toggle component.

[02:13] We'll call the toggle components set-on-state function with a new value based on the previous toggle components on-state. Now this set-on-state has not been defined yet, so let's go write that.

[02:37] There's actually a lot of complexity in this component that we can just get rid of. It no longer needs a reference to its child components, doesn't need any of this stuff down here. All we need is the set-on-state function that takes a boolean value and updates the internal state and then emits a new value, and I'll clean up here.

[03:10] Now if we go back to our app component HTML, we have multiple copies of toggle-on and toggle-off. We have an other component that has toggle-on and toggle-off inside of it. Let's see if this works.

[03:22] You see that all the toggle-on and toggle-off components, no matter how deeply nested they are, are receiving their state from the top-level toggle component.

Bruno Ribeiro
Bruno Ribeiro
~ 5 years ago

How do Angular know which instance of "ToggleComponent" should be injected into each child component? It's always the parent one?

SoftwarePlant
SoftwarePlant
~ 5 years ago

I have the same question as Bruno above. This part seems to be magic. How angular knows this?

Manuele
Manuele
~ 5 years ago

it's the first time I see injecting a parent component through the constructor, i didn't even know it was possible, I thought only services could be injected, thank you!

Isaac Mann
Isaac Manninstructor
~ 5 years ago

Angular knows about the tree of components that are being rendered in your app. So it starts at the component that is trying to inject the ToggleComponent and then walks up the tree until it finds the first instance of ToggleComponent. This process is controlled by the ElementInjector.

If it doesn't find a ToggleComponent in the component tree, it will look for it in the providers of the modules that are loaded.

If it still doesn't find it, Angular will throw an error. (You can avoid that error by adding @Optional() where you inject it.)

For more detailed explanation, you can check out these two articles:

  1. A curious case of the @Host decorator and Element Injectors in Angular

  2. What you always wanted to know about Angular Dependency Injection tree

Bruno Ribeiro
Bruno Ribeiro
~ 5 years ago

Fantastic! Thanks Isaac, this sounds really useful

gabriel
gabriel
~ 5 years ago

I don't see where this pattern could be useful...the example is so contrived.

Isaac Mann
Isaac Manninstructor
~ 5 years ago

@gabriel This pattern basically let's you implement a pub-sub pattern where the parent component (publisher) doesn't need to know about the child components (subscribers). And the child components can be nested arbitrarily deep within the parent component.

Oscar Lagatta
Oscar Lagatta
~ 5 years ago

Hi Isaac, what's the difference between the ToggleOnComponent and the ToggleOffComponent in regards the constructor? You do one toggle constructor injecting the ToggleComponent as private and the other toggle injecting as public, what's the reason behind that ? great course, Thank you!!! Oscar

Isaac Mann
Isaac Manninstructor
~ 5 years ago

@Oscar, good catch. They should both be public. They're both public in the code on Stackblitz.

private injected objects can not be referenced in the template of the component. Since we're referencing the parent toggle.on property in both templates, it should be public.

I generally try to keep all injected dependencies private, unless they need to be public.

Guru Inamdar
Guru Inamdar
~ 5 years ago

Hi Issac, thank you very much for the course,

qq - why are we using this.toggle.on inside toggle button and then send the value back to parent via setOnState? like this

setOnState() {
    this.on = !this.on;
    this.toggle.emit(this.on);
  }
Isaac Mann
Isaac Manninstructor
~ 5 years ago

In this lesson I'm showing how to keep the state of the toggle in the parent toggle component. The button component needs to tell the parent component to update the state so all the other components can update.

Ajay Kumar
Ajay Kumar
~ 5 years ago

@Isaac Thanks for the course. Should we use component constructor pattern instead of Input\Output pattern for sharing any information with child components. Thanks Ajay.

Markdown supported.
Become a member to join the discussionEnroll Today