1

I have a situation where based on the input selected (radio or checkbox), I add a component dynamically through ajax.

Plunkr: https://plnkr.co/edit/uvGo3RxCkUPeuknVu9m8?p=preview

I explain the flow for better understanding:

First Layer: src/parent/parent.ts

We get the json response from questions.json and populate the questions.

Based on the controlType we load either a-component or b-component in src/parent/parent.html.

When I select a checkbox in a-component or a radio button in b-component, I call createDynamicComponent() and pass in the componentData.

componentData is nothing but the metadata information on the next component that needs to be populated, based on the selected option.

Now, the componentData is passed into the dynamic-component from src/controls/a.html or src/controls/b.html

Inside dynamic-component, I resolve the provider and inject the questions data into the entryComponents, (a-component and b-component)

Everything was working fine, until I introduced a HService (which holds the component data building logic) inside both a-component and b-component.

I am getting the following error, Error: Can't resolve all parameters for BComponent: ([object Object], [object Object], ?)

The last parameter being the HService inside the constructor of b-component, If I take out the service and use the commented code, everything works fine.

this.componentData = {
  'questions': {
    "question": "This is a " + this.level + " level question?",
    "controlType": "radio",
    "answers": [
        "Yes",
        "No",
        "None"
    ]
  },
  "component": BComponent,
  "level": this.level
};

Edit 1: I have the HService injected into a-component already and there is no provider resolve error and it is working fine. Only on adding it to b-component, I face the error.

Help will be much appreciated!!

1 Answer 1

3

I think the problem is based on circular dependencies.

A <=> HService and B <=> HService

To solve it i would unleash dependencies by creating abstract class for HService and use it as token:

base.h.ts

export abstract class BaseHService {
    private componentData: any;

    abstract getComponentData(queries: IQ[], level: number): any;
}

app.module.ts

providers: [ 
  { provide: BaseHService, useClass: HService }, <== this line
  { provide: 'questions', useValue: {} }, 
  { provide: 'level', useValue: 1 }
],

a.ts

import { BaseHService } from "../h/base.h";
...
constructor(...private _h: BaseHService) {

b.ts

import { BaseHService } from "../h/base.h";
...
constructor(...private _h: BaseHService) {

Modified Plunker

Sign up to request clarification or add additional context in comments.

3 Comments

Nice catch but do you think this is a good pattern to follow? I mean a component creating a dynamic component in itself with the same type.. recursively adding it to itself.. mind.. blown. The dynamic component injection part should be seperated in a service in my opinion but not sure.
@yurzui thanks for the solution. It is working great. So much to understand and learn in Angular2
@echonax I am thinking of making the dynamic component injection part into a service. Will look into it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.