2

what's the correct RXJS approach to passing numbers within an Angular 5 app (no API)?

I've successfully passed a boolean with Subject :

service :

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';

@Injectable()
export class IsOpened {

  data = new Subject();

  constructor() {}

  insertData(data){
    this.data.next(data);
  }
}

emitter :

toggle(){
    this.opening = !this.opening;
    this._isOpened.insertData(this.opening);
}

listener :

ngAfterViewInit() {
    this._isOpened.data.subscribe((value) => {
      if(value) this.opened = true;
      else this.opened = false;
    }});
}

I sorta cheat in the listener because I don't store the received value but rather assess that and re-create the boolean.

works for me and fits in very few lines.

I can't do the same with numbers.

enter image description here

how would I do it with numbers? with arrays?

Google and the many RXJS info sources yielded nothing.

tatsu
  • 2,316
  • 7
  • 43
  • 87

1 Answers1

3

Here is an example of how to use Subject/BehaviorSubject with an object. This same technique would work for numbers.

Service

export class ProductService {
    private products: IProduct[];

    // Private to encapsulate it and prevent any other code from
    // calling .next directly
    private selectedProductSource = new BehaviorSubject<IProduct | null>(null);

    // Publicly expose the read-only observable portion of the subject
    selectedProductChanges$ = this.selectedProductSource.asObservable();

    changeSelectedProduct(selectedProduct: IProduct | null): void {
        this.selectedProductSource.next(selectedProduct);
    }
}

Component setting the value

  onSelected(product: IProduct): void {
    this.productService.changeSelectedProduct(product);
  }

In this case, when the user picks something in one component, the selection is broadcast to several others.

Component reading the value

ngOnInit() {
    this.productService.selectedProductChanges$.subscribe(
        selectedProduct => this.product = selectedProduct
    );
}

In this example, the component reading the value stores it into its own local variable. That variable is used for binding and the UI changes based on the selected product.

NOTE: You can achieve this SAME functionality using getters/setters with NO subject/behavior subject.

I have a complete example using Subject/BehaviorSubject here: https://github.com/DeborahK/Angular-Communication/tree/master/APM-Final

And the exact same functionality with getters/setters instead of Subject/BehaviorSubject here: https://github.com/DeborahK/Angular-Communication/tree/master/APM-FinalWithGetters

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • I thought Angular 5 devs were encouraged to switch to observable all round? is there more benefit in the case of an internal value swap to getters and setters? since many many of my components are awaiting these values and since they update very frequently I opted for Observables at the start of my refactor. – tatsu Feb 28 '18 at 16:37
  • Angular's change detection already handles notifications for you when your templates bind to the result. In that case, using a getter/setter is just easier and more straightforward. But when you *need* notifications or want to handle async operations, Observables are the way to go (vs promises for example). – DeborahK Feb 28 '18 at 16:39
  • 1
    Because it is not my example and does not match with the provided github. If you have a more on-point answer, feel free to copy my code, change it to match your number example, and mark it as your answer instead. :-) – DeborahK Feb 28 '18 at 17:24