0

I would like to store a value in a service which any component can watch and change, and when any component changes the value, all other components watching the value will be updated.

After some research, i have found this solution that makes sense to me but does not work.

https://plnkr.co/edit/mlVfASdAw1vbpJRhGFov?p=preview

Service

        export class Service {
            value: string;
            subject: Subject<string> = new Subject<string>();
            setValue(value: string): void {
                this.subject.next(value);
            }
            getObservable(): Observable<string> {
                return this.subject.asObservable();
            }
        }

Component 1

        @Component({
            selector: 'comp-1',
            template: `
                <div>
                Value in component 1: {{value}}
                </div>
                <button (click)="update()">set value to '1'</button>
            `,
            providers: [Service]
        })
        export class Component1 {
            subscription;
            value: string;
            constructor(private service: Service) {
                this.headerStateSubscription = this.service.getObservable().subscribe(value => {
                    this.value = value;
                });
            }
            update() {
                this.service.setValue('1')
            }
        }

Component 2

        @Component({
            selector: 'comp-2',
            template: `
                <div>
                Value in component 2: {{value}}
                </div>
                <button (click)="update()">set value to '2'</button>
            `,
            providers: [Service]
        })
        export class Component2 {
            subscription;
            value: string;
            constructor(private service: Service) {
                this.headerStateSubscription = this.service.getObservable().subscribe(value => {
                    this.value = value;
                });
            }
            update() {
                this.service.setValue('2')
            }
        }

3 Answers3

1

You should use singleton service instead of individual instance for each of component. So remove

providers: [Service]

from components metadata and add it to AppModule or common parent component

Plunker Example

yurzui
  • 205,937
  • 32
  • 433
  • 399
1

Angular2 components have a far better way of notifying parent/child components that something has changed, via events. There’s no longer two-way data binding in Angular in the same way we knew it in AngularJS, it’s designed around a uni-directional data flow system that adopts a much more reasonable approach to application development.

In bigger or more complex application is better to use redux pattern.

Angular2 Documentation

StackOverflow - What is the proper use of an EventEmitter?

Build a Better Angular 2 Application with Redux and ngrx

Krzysztof Lach
  • 1,280
  • 1
  • 12
  • 19
0

I have Updated your plunker for it to work

link - https://plnkr.co/edit/grcuPBYTiDNRfo26UVbB?p=preview

changed service and providers

 value: string;

  subject: Subject<string> = new Subject<string>();

  constructor() {  }

  setValue(value: string): void {
    this.value = value;
    this.subject.next(this.value);
  }

@NgModule({
  imports: [ BrowserModule ],
  declarations: [
    App,
    Component1,
    Component2
  ],
  bootstrap: [ App ],
  providers:[Service]
})

But ngrx is the better approach for you to prevent spaghetti code

This a classic case of using ngrx or the redux pattern

Please check this link for Angular Ngrx Example.

https://rahulrsingh09.github.io/AngularConcepts

-> Advanced Concept -> ngrx store

Rahul Singh
  • 19,030
  • 11
  • 64
  • 86