tmanion
tmanion

Reputation: 401

Angular 2 RXJS - Can't get Components to Talk

I'm having trouble getting two components to talk through an Injectable service. I cant quite figure out what I'm doing wrong here.

I have:

The goal is to have the Login service notify the navbar that the user is logged in, and display links appropriately. I'm using RXJS to have the Login Component set the next value of the User Service's BehaviorSubject, which is supposed to notify the navbar subscriber.

My code for these to talk looks like the following:

Login Component

@Component({...})
export class Login implements OnInit {
  constructor(fb: FormBuilder, private http: Http, private router: Router, public userService: UserService) {
    this.loginForm = fb.group({
      email: ["", Validators.required],
      password: ["", Validators.required]
    });

    var val = false;
    setInterval(() => {
        val = !val;
        userService.setNextIsLoggedIn(val);
    }, 1000);
  }
}

User Service

@Injectable()
export class UserService {
    jwtToken: string;
    public isLoggedIn: Subject<boolean> = new BehaviorSubject<boolean>(false);

    setNextIsLoggedIn(val) {
        console.log('gets here!');
        this.isLoggedIn.next(val);
    }

}

Navbar Component

@Component({
    selector: 'navbar',
    template: require('./navbar.html'),
    styles: [style],
    directives: [RouterLink, NgClass, NgIf],
    providers: [UserService],
    changeDetection: ChangeDetectionStrategy.OnPush
})

export class Navbar implements OnInit {
    isLoggedIn: boolean = false;
    constructor(private location: Location, public userService: UserService) {}

    isLocationEqual(loc:string):boolean {
        return this.location.path() === loc;
    }

    ngOnInit(): void {
        this.userService.isLoggedIn.subscribe((isLoggedIn: boolean) => {
            console.log('RECEIVED!!', isLoggedIn);
            this.isLoggedIn = isLoggedIn;
        });
    }
}

The Login Component talks to the User Service fine. If I put a subscribe statement in the UserService, it receives every update. However, the Navbar only receives the FIRST value from its subscribe.

Does anyone have any ideas what I'm doing wrong?!

Upvotes: 0

Views: 129

Answers (1)

Patrick Opie
Patrick Opie

Reputation: 11

It's possible this is a cold vs hot observable issue. Angular 2 by default uses cold observables where values are not being shared on subscriptions. You would want to consider using a hot observable or use a single stream to house all the logic.

documentation on cold vs hot observables.

You can use an event emitter as well:

function toRx ( eventEmitter ) {
  return Rx.Observable.create(function ( observer ) {
    eventEmitter.subscribe(function listener ( value ) {observer.onNext(value)});
    // Ideally you also manage error and completion, if that makes sense with Angular2
    return function () {
      /* manage end of subscription here */
    };
  };
)
}

Once you have that Rx.Observable, you can apply share() to share with additional streams.

Upvotes: 1

Related Questions