6

So I know you can have two unrelated components communicate with each other via a service by having one component emit an event in the service and the other subscribe to it in the service.

My question:

Can a service call a function in a component directly?

3
  • If you have a reference in your service to the component, sure. But I wouldn't recommend the two classes referring to each other. Commented Mar 30, 2016 at 13:12
  • 1
    so basically the event throwing and subscribing method is best practice? Commented Mar 30, 2016 at 13:13
  • Definetely. You can do that with observers. You want to keep it seperated in order to keep separations of concerns. The answer of Günter seems to be correct. Commented Mar 30, 2016 at 13:16

2 Answers 2

16

Not by default. A service is an instance of a class, nothing more.

@Injectable()
class MyService {
}

@Component({
  selector: 'my-component',
  ...
)}
class MyComponent {
  constructor(private myService:MyService) {}
}

@NgModule({
  providers: [MyService],
  ...
})
export class AppModule {}

This way a service (MyService) instance gets passed to MyComponent but that is all. The service instance has no knowledge about MyComponent.

What you probably want is to add an Observable to your service and subscribe to it in your component.

@Component({
  selector: 'my-component',
  ...
)}
class MyComponent {
  constructor(myService:MyService) {
    myService.someObservable.subscribe(value => doSomething(value));
  }

  doSomething(value) {
    console.debug(value);
  }
}

this way the service "calls" a method on the component when the Observable someObservable emits another value.

For more details see detect change of nested property for component input

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

5 Comments

You must ensure the injected MyService in component and the one in other place refer to the same object. Otherwise, the component will fail to respond to the MyService's event.
That is by providing it not directoly at the component but on a common parent (or AppComponent which is the common parent of the whole application, or in bootstrap())
You are right. I just notice others. you get a nice solution.
Better solution would be to use Subject instead of Observers/ables. github.com/Reactive-Extensions/RxJS/blob/master/doc/api/…
It would be more helpful if you code provide the service someObservable code too
1

The answer above is correct except that you don't bootstrap your service, you will add your service in your providers array in the app.module.

@NgModule({
    declarations: [MyComponent],
    imports: [],
    providers: [MyService],
    bootstrap: [AppComponent]
})

Then you inject your service inside of the component

import { Component } from '@angular/core'

import { MyService } from './path/to/my.service'

...

export class MyComponent {

    constructor(private myService:MyService){}

}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.