3

I have an Angular2 component that uses 2 sub components. The template looks like

<component-A/>
<component-B/>

I would like to inject the component-A instance into the constructor of component-B. Is there a way to refer to component-A in a provider on my root component?

jz87
  • 9,199
  • 10
  • 37
  • 42
  • lI don't think constructor injection is possible for this scenario. Could you please elaborate a bit more what you actually try to accomplish? There might be other ways to achieve it. What do you need the refetence to A for? – Günter Zöchbauer Jan 16 '16 at 12:16
  • I have 2 components, one is a design surface, and the other is a control panel for the design surface that sets the mode: Drawing, Selection, etc. I would like the control panel to take an instance of the design surface component as an injection. – jz87 Jan 16 '16 at 13:03
  • 2
    I don't know if this is possible, but to me it doesn't make sense to couple the components like this. In order to share code between them I would recommend sharing the logic via services instead. – TGH Jan 16 '16 at 16:03

1 Answers1

1

That breaks the whole purpose of making two components in the first place. Since you are making one dependant on the other you can't reuse them separately, might as well make them one.

Create a parent that holds both components inside and the info they both need and set that info to each children component as @Inputs:

https://angular.io/docs/ts/latest/api/core/Input-var.html

some raw example:

<component-A (modeSelected)="selectedMode==$event"/>
<component-B [mode]="selectedMode" />

or:

<component-A #modeSelector/>
<component-B [mode]="modeSelector.selectedMode" />

() means output, [] means input.

In the first example selectedMode is a property of a parent controller that holds both A and B components inside. In the second example selectedMode is a property of component A.

Langley
  • 5,326
  • 2
  • 26
  • 42
  • That's not really true, because I would like to abstract the design surface to an interface. I might have different type of design surfaces in the future all with the same need to toggle between the same set of modes. – jz87 Jan 16 '16 at 19:30
  • what do you mean by design surface? – Langley Jan 16 '16 at 19:37
  • Oh ok I read your comments in the question, so the way to do this is, the control panel component sends an `@Output` to the parent component telling him the selected mode, the parent holds this selected mode in a property that passes as an `@input` to the Design Surface component, the Design Surface components reacts when this value changes updating the model the template is based upon. – Langley Jan 16 '16 at 19:42
  • I updated the answer to show some raw examples of how to do this. – Langley Jan 16 '16 at 19:46
  • Hmm, there is no way to hook up the control panel to the design surface directly? The problem with this approach is that every root component that uses these 2 components would have to know about all modes and everything. I would like to have a ComponentA, and a ComponentA-Controller. The controller provides UI to manipulate the settings of ComponentA. The details of what properties need to be manipulated are preferably opaque to the root component. The root component should just be responsible for hooking the two up. – jz87 Jan 16 '16 at 20:55
  • Right now I'm hooking it up via input property. , but constructor injection would be preferable. – jz87 Jan 16 '16 at 21:03
  • Take a look at [this](http://stackoverflow.com/questions/34575897/passing-a-component-as-an-argument-to-another-component-in-angular-2/34576997#34576997). I changed component design since then, but [service](http://stackoverflow.com/questions/34802210/angular-2-child-component-events-broadcast-to-parent/34807012#34807012) I use to communicate between components didn't change, works for any scenario - parent/child or sibling components... – Sasxa Jan 16 '16 at 23:08
  • Why would injecting the whole component in the constructor would be preferred? you don't need the whole component, the whole resposability of the first component is to choose a mode, and all the component B needs to know is which mode do you want to render the component as and for that you don't need the whole other component, just the mode. – Langley Jan 16 '16 at 23:11
  • Let's say ComponentA implements an interface IComponentA that has a bunch of properties on it. ComponentA-Controller exposes an UI to set those properties. The point is to inject an instance of IComponentA into the constructor of ComonentA-Controller as the target component to manipulate. Normally if ComponentA were a service this would be easy. The main issue is ComponentA is created in the component template of a root component. In this example the interface is rather simple, just a Mode. But in the future I would like to be able to add more complex interfaces. – jz87 Jan 17 '16 at 02:01