0

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

Kumail Hussain
  • 869
  • 2
  • 26
  • 49

3 Answers3

3

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);
Community
  • 1
  • 1
AT82
  • 71,416
  • 24
  • 140
  • 167
  • its not working when components are on different route say localhost:4200/receive---ist component laoded say lcaolhost:4200/sender---2nd component loaded now if i send message from sender to receiver its not updating ist component its working when local:420/message---both components are loaded on this route then its work good but i need solution for components on different routes – Kumail Hussain May 02 '17 at 10:10
  • Yes it should work... just to make sure... what do you mean with *different route*? – AT82 May 02 '17 at 10:11
  • i have explained above can you see that – Kumail Hussain May 02 '17 at 10:13
  • Well then it should work fine. Did you even try the code? That is why I presented BehaviorSubject, because it will always subscribe, in contrary where Subject subscribes only when something is emitting. – AT82 May 02 '17 at 10:18
  • what you meant by routing involved? – Kumail Hussain May 02 '17 at 10:18
  • and its working fine when both components are same i have explained the case obove – Kumail Hussain May 02 '17 at 10:19
  • With routing I mean that one component sets the value and then it routes to other component. Could you please explain how these components are sort of "related". And now I don't mean relationship like parent child, but rather how this is setup. And what do you mean with *components are same*? Well, and I am trying to explain that BehaviorSubject doesn't behave like a Subject. Subject needs next() called, wheras BehaviorSubject doesn't need that. If there is a value, BehaviorSubject will always subscribe. – AT82 May 02 '17 at 10:23
  • no both components are independent there is no routing between the component – Kumail Hussain May 02 '17 at 10:25
  • Okay, are they both shown together in the view tho? For example, one would be considered a navbar and other as "content"? – AT82 May 02 '17 at 10:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143175/discussion-between-kumail-hussain-and-ajt-82). – Kumail Hussain May 02 '17 at 10:31
1

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

Trash Can
  • 6,608
  • 5
  • 24
  • 38
  • it didn't work its same as the shared service if there is relationship between components then it will work otherwise it will not – Kumail Hussain May 01 '17 at 20:53
  • It works regardless, I have been using services to communicate between my components since I started using angular, so. – Trash Can May 01 '17 at 21:14
  • what i am trying to is update the ist component based on the second one but there is no relation between these component – Kumail Hussain May 01 '17 at 21:18
  • i.e both components are on different routes – Kumail Hussain May 01 '17 at 21:23
  • So based on what you said, one component may exist while the other may not be created yet until you navigate to the router associated with it? If that is the case, then my answer is not gonna work, as a matter of fact, nothing will work, you can't communicate with somebody that does not exist yet – Trash Can May 01 '17 at 21:41
  • if the second route is activated can we update it ?can there be a notification mechanism like that – Kumail Hussain May 01 '17 at 21:42
  • as long as they both exist, they can communicate. That's why observables are really powerful, no matter when a subscriber subscribes to it, as long as somebody is still subscribed to it, then that subscriber will receive new updates from the observable. Here `SharedService.setState` allows you to push the update down to the subscribers letting them know that something new arrives – Trash Can May 01 '17 at 21:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143127/discussion-between-kumail-hussain-and-dummy). – Kumail Hussain May 01 '17 at 21:47
0

Use ngrx

RxJS powered state management for Angular applications, inspired by Redux

https://github.com/ngrx/store

Julia Passynkova
  • 17,256
  • 6
  • 33
  • 32