0
votes

i have two separate components, there is no relationship of one component on other but my purpose is to communicate these components i know shared services with emitter can share data between parent-child components what if there is no relation between the components but have to change one component based on othe for example:

    import {Component,bind,CORE_DIRECTIVES,OnInit} from 'angular2/core';
import {MainComponent} from 'src/MainComponent';
import {SharedService} from 'src/shared.service';
@Component({
    selector: 'my-app',
    directives:[MainComponent],
    template: `<h1>AppComponent {{onMain}}</h1>
    <div *ngIf="onMain == false">
       Hello
      <br> __________________________________<br>
    </div>


    })

export class AppComponent implements OnInit {
  onMain: Boolean;

  constructor(ss: SharedService) {
      this.onMain = false;
      this.ss = ss;
    }



    ngOnInit() {
    this.subscription = this.ss.getMessage()
      .subscribe(item => this.onMain=item);
  }

}

2nd component

    import {Component,bind,CORE_DIRECTIVES} from 'angular2/core';
import {SharedService} from 'src/shared.service';
@Component({
    selector: 'main-app',

    template: `<h1> MainComponent</h1>
    <button (click)="changeName()">Change Name</button>
    `
})

export class MainComponent {



    constructor(ss: SharedService) {
      this.ss = ss;
    }

    changeName() {
      this.ss.sendMessage(true);
    }
}

sharedservice

    import { Subject } from 'rxjs/Subject';

@Injectable()
export class LandingService {
    private subject = new Subject<any>();

    sendMessage(message: any) {
        this.subject.next({ text: message });

    }

    clearMessage() {
        this.subject.next();
    }

    getMessage(): Observable<any> {
        return this.subject.asObservable();
    }
}

the problem is both components are not inter-related they are running on two different routes but from 2nd component click i want to change the value of OnMain declared in the first component basically I want to update component or send a signal to first component that value has changed and update it accordingly.

its possible or not help will be appreciated

3

3 Answers

3
votes

Let's see if I understood this correctly...

You probably want a BehaviorSubject. The difference between a Subject and BehaviorSubject is:

Behavior subject needs a initial value as it must always return a value on subscription even if it hasn't received a next(). Upon subscription it returns the last value of the subject. A regular observable only triggers when it receives a onnext.

So when your other component might not have been created yet, the regular Observable won't fire when you e.g navigate to that component, where there would be a subscriber to the Observable. BehaviorSubject on the other hand always emits value if there is a subscriber.

So your service would look something like this:

// BehaviorSubject needs an initial value
private message = new BehaviorSubject<Object>(null); 

message$ = this.message.asObservable();

sendMessage(message) {
  this.message.next({text: message});
}

Your changeName:

changeName() {
  this.ss.sendMessage(true);
}

And the component that subscribes to this:

this.ss.message$ // subscribe to the Observable
  .subscribe(item => this.onMain = item);
1
votes

Use Subject instead, it allows you to subscribe to it to receive notifications, it is like an Observable in the sense that you can subscribe to it, and push data to all subscribers, it is not an observable which offers different operators like how RxJS Observables do

import { Subject } from 'rxjs';


@Injectable()
export class SharedService {
  private state = new Subject<boolean>();

  // Push a state change notification to all subscribers
  updateState(newState: boolean) {
    this.state.next(newState);
  }

  getState(): Subject<boolean> {
    return this.state;
  }
}

Now just inject the service into your components

export class AppComponent implements OnInit {
  onMain: Boolean;

  constructor(ss: SharedService) {
      this.onMain = false;
      this.ss = ss;
    }


    ngOnInit() {
      this.subscription = this.ss.getState()
        // Just subscribe to the Subject to receive notification
        .subscribe(currentState=> {
          console.log(currentState); // 
        });
    }

    onClick() {
      // Update the state of the shared service so that you can send any notification to all the subscribers
      this.ss.setState(true);
    }

}

You can do the same for the other component. Just subscribe to it to receive notification of change

0
votes

Use ngrx

RxJS powered state management for Angular applications, inspired by Redux

https://github.com/ngrx/store