Jason
Jason

Reputation: 151

Angular 2 How to detect string change using observable

I have 2 services. In one I want to subscribe to detect if a string changes in the other service to load from the database each time it changes.

First service:( The session value used is a reference to the 2nd service)

subscribeStringChange() {
    this.session.uid.subscribe(x => {
        console.log(this.session.uid);
        return this.af.database.list('items', {
            query: {
                orderByChild: 'uid',
                equalTo: this.session.uid
            }
        });
    });
}

Here is the second service and what I have tried:

uid: Observable<string> = Observable.of('');

constructor(private auth: FirebaseAuth, private af: AngularFire) {
    this.auth.subscribe(user => {
        if (user) {
           this.uid = Observable.of(user.uid);
            console.info('logged in');
        } else {
             this.uid = Observable.of('');
            console.info('logged out');
        }
    });
}

Upvotes: 3

Views: 2753

Answers (2)

Paul Samsotha
Paul Samsotha

Reputation: 208944

You could use a BehaviorSubject, which acts like both a producer and consumer (or more precisely, observer and observable). On the side where you use firebase, you would be acting on the producer side, emitting the new value, and on the other side, you just keep it the same

import { BehaviorSubject } from 'rxjs/BehaviorSubject';

private _uid = new BehaviorSubject<string>('');

uid = this._uid.asObservable();

constructor(private auth: FirebaseAuth, private af: AngularFire) {
    this.auth.subscribe(user => {
        if (user) {
           this._uid.next(user.uid);
            console.info('logged in');
        } else {
             this.uid.next('');
            console.info('logged out');
        }
    });
}

Notice the this._uid.next(''). Here you are emitting a new value, and the subscriber(s) will receive it.

You don't need to change anything in the other service. Well actually you do. You are trying to access the uid, which is an observable, when you should just use the value passed to the subscribe callback, x

this.session.uid.subscribe(x => {
    console.log(x);
    return this.af.database.list('items', {
        query: {
            orderByChild: 'uid',
            equalTo: x
        }
    });
});

Upvotes: 2

Sasxa
Sasxa

Reputation: 41254

You've made things more complicated then they should be (: In general, you should use subscribe() to assign end result of observable chain to a variable (for use in templates, for example). You shouldn't process observables in subscription...

Here's one solution you could use:

subscribeStringChange() {
  // when user is authenticated
  this.af.auth.filter(Boolean)
    // get her 'uid'
    .map(user => user.uid)
    // and use it in another observable
    .switchMap(uid => this.af.database.list('items', {
            query: {
                orderByChild: 'uid',
                equalTo: uid
            }
        })
    // finally, do something with the results
    .subscribe(snap => console.log(snap));
}

Make sure you import operators somewhere in your code, in this case:

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';

Upvotes: 1

Related Questions