0

Say we have this component:

@Component({

  template: `
   <div *ngFor="let v of values;" #aService="getServiceInstance()">
      <child-component1 [s]="aService"></child-component1>
      <child-component2 [s]="aService"></child-component2>
   </div>
 `

})
export class MyComponent {

  values = [1,2,3,4,5];

  getServiceInstance(){

      // ??? how to implement this ???

  }

}

my question is - how can I implement the getServiceInstance() method so that I inject a new service instance into the child-component? Is there a way to do that somehow? Maybe using a decorator?

I am guessing that something like this is possible:

 @Inject(MyService)
 getServiceInstance(ms: MyService){

    ms.13 = 'dangerous';
    return ms;

 }

but that's just a guess.

4
  • 1
    You are mixing separation of concerns. The template code should not care or know about services, it should interact with the component it is defined for and any child components it references. The component interacts with services(s). What you are trying to do is bad design but I suspect this is an x y problem. Update your question with what it is you are actually trying to accomplish, not how you are trying to accomplish it. Commented Feb 1, 2018 at 19:22
  • A service instance is just an object - I want to create a shared object dynamically, so that it can be shared between grandchildren and cousins alike. So that they can communicate. Maybe @Input is really no different. But I need to create a new object (a new service) for each element in the values array. Commented Feb 1, 2018 at 19:24
  • 1
    Then you can create a complex object (instead of just a number) in the values array that contains a service and the number. Use a factory service to create an instance of a service per item in the array at the time the array is created/mutated (whatever). Then you can reference this service in the *ngFor loop in the template should you want to pass the service to the child component. Commented Feb 1, 2018 at 19:28
  • that's a good point, probably a better idea, but I still need to inject a new service instance, so maybe I have to call the same method, but just not from the HTML Commented Feb 1, 2018 at 19:33

2 Answers 2

2

Then you can create a complex object (instead of just a number) in the values array that contains a service and the number. Use a factory service to create an instance of a service per item in the array at the time the array is created/mutated (whatever). Then you can reference this service in the *ngFor loop in the template should you want to pass the service to the child component.

You would need to provide the implementations / definitions of Service and ServiceFactory but this should illustrate the point.

@Component({
  template: `
   <div *ngFor="let v of enrichedValues">
      <child-component1 [s]="v.service"></child-component1>
   </div>`
})
export class MyComponent implements OnInit {

  @Input()
  values = [1,2,3,4,5];

  enrichedValues: {value:number, service:Service}[];

  constructor(private serviceFactory: ServiceFactory){
  }

  ngOnInit(){
    this.enrichedValues = this.values.map(val => {value: val, service: this.serviceFactory.createService()});
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

cool, what does the ServiceFactory look like? can you show a simple implementation?
@AlexanderMills - I have no idea, you never provided any detail on what and why you want to create a service per instance. A factory pattern is just some type that creates other complex instances based on some business logic. That is what I gathered you needed based on your last comment.
@AlexanderMills - if you want to share the same instance then you could basically replace the word ServiceFactory with Service and assign it directly instead of calling it. I will add a second example.
Assume what you have is what I want. Next, how do you actually generate a service instance, where there is more than one instance of that service per factory class. The only way I can think of, is to use @Inject with a method instead of the constructor, but you tell me
I edited the second part of your answer because it went off topic
1

Why don't create that service as a separate service with @Injectable decorator and then inject that service in the child-component-s.

@Injectable()
export class YourService { ... }

...

@Component({...})
export class ChildCmp {
   constructor(private yourService: YourService)
}

You can do something like

getServiceInstance() {

   return () => {
      // Your logic here
   };

}

but I don't think this is a good solution cause I don't understand why you want to do things like that.

6 Comments

I need more than one instance of YourService - I need as many instances of the service as I have values in the values array
This is also another question why not a single service, but you can add the YourService into the providers of the ChildCmp, not into the providers of the module - this lets each ChildCmp has it's own instance of YourService
I added more details, hopefully you understand now. I want sibling components to share the same service instance
I think you will enjoy the question if you choose to do so :)
:) What a question.
|

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.