Search code examples
angularrxjsstore

Use an observable store and a component input with Angular


I developed a custom angular store using a BehaviorSubject and I'm using like this:

export class UserFaceComponent {

    @Input()
    public id: any;

    public presence$: Observable<boolean>;

    constructor(private _store: Store) { }

    public ngOnInit() {
        this.presence$ = this._store
            .select(s => s.users.presences)
            .pipe(
                map(p => p.includes(this.id))
            );
    }
}

This way, when the store changes, the presence$ observable emits a new value. It works well, however, the id passed to the component could also change. Say there is a list of user on the page and when the user selects one of them, it updates a variable selectedUserId that is passed to the UserFaceComponent. This would be the same component as before but id would be updated.

This means that I have to create a subject in my component, subscribe to the onChange hook and emit on this subject when id changes. Then, I have to merge this observable with the one above and then emit the new value.

This would work but it is pretty cumbersome and I don't want to be forced to do this for each component made with this approach... I'm thinking about it for a while but I can't find another solution to tackle this...


Solution

  • I came accross the same requirement several times and unfortunately there is no simpler solution as your onChange-subject approach. I read once there was a suggestion of an ObservableInput decorator, but it never was implemented.

    Besides your approach there is just one another way to do this, it is not really simpler, just different. This alternative approach uses input getters and setters instead of the ngOnChanges lifecycle hook to update the subject.

    private _id: BehaviorSubject<string> = new BehaviorSubject<string>();
    @Input()
    set id(value: string) {
      this._id.next(value);
    }
    get id(): string {
     return this._id.value;
    }