Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject the instance of a component in a service

Tags:

angular

inject

For a any good reaon, I am trying to inject my component into a service, but I obtain a new instance of it. I reproduce my problem with this code :

This component will display the instance number in h1 :

@Component({
    selector: 'my-component',
    template: '<h1>Instance number {{count}}</h1>'
})
export class MyComponent {
    private static i = 0;               /* <-- counts the myComponent's instances here */
    private _count: number = i++;
    get count(): number {return this._count}
}

The Service will log the instance number in console:

@Injectable()
export class MyService {
    constructor(myComponent: MyComponent) {
        console.log("Instance number " + myComponent.count);
    }
}

The main component will inject the component in a view and the service :

@Component({
    selector: 'app-root',
    template: '<my-component></my-component>',
})
export class AppComponent {
    constructor(service: MyService) {
    }
}

I'm using angular-cli, my app.module.ts looks :

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

Currently, my console displays Instance number 0 and my html display Instance number 1. How can I obtain the same instance ?

Thanks for reading me

like image 582
Karbos 538 Avatar asked Dec 01 '16 14:12

Karbos 538


2 Answers

This doesn't work. If your application has several instances of this component, which one should it inject.

What you can do is for example to inject the service to the component and make the component pass itself to the service

@Component({
    selector: 'my-component',
    template: '<h1>Instance number {{count}}</h1>'
})
export class MyComponent {

    constructor(service: MyService) {
      service.myComponent = this;
    }

    private static i = 0;
    private _count: number = i++;
    get count(): number {return this._count}
}

It's better to not pass components to services but instead use observables to notify components about events and let components do the rest.

For more details see https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

like image 89
Günter Zöchbauer Avatar answered Sep 20 '22 15:09

Günter Zöchbauer


Thanks for your answer @Günter. I post my new component with service subscription here for anybody interested in :

The observable service :

@Injectable()
export class MyService implements OnDestroy {
    private _count:number = 0;
    public numberSource = new Subject<number>();
    private numberObservable: Observable<number> = this.numberSource.asObservable().share();

    public count() {this.numberSource.next(this._count++);}
    public subscribe(s: any) {return this.numberObservable.subscribe(s);}
    public ngOnDestroy() {this.numberSource.complete();}
}

A subcriber component (I can have many) :

@Component({
    selector: 'my-component',
    template: `
<button (click)="increment()" >Count !</button>
<div *ngFor="let n of numbers">{{n}}</div>
`
})
export class MyComponent {
    private numbers: number[] = [];
    constructor(private myService: MyService) {
        myService.subscribe((n:number) => this.numbers.push(n));
    }
    increment() {
        this.myService.count();
    }
}

I don't know if I'm clear, but this is exactly what I was looking for. Thanks !

like image 28
Karbos 538 Avatar answered Sep 21 '22 15:09

Karbos 538