Dennis Ich
Dennis Ich

Reputation: 3775

RxJS observable of objects property

I want to observe changes of a property with RxJS.

interface Test {
  required: boolean;
  toObserve: boolean;
}

class TestClass {
  @Input() subject: Subject<Test>;

  registerHandlers() {
    this.subject.filter(element => element.required).subscribe(next =>
      // Observe a property of every element that was registered
      Observable.of(next.toObserve).subscribe(val => {
        if (val) {
          // DO SOMETHING
        } else {
          // DO SOMETHING ELSE
        }
      })
    );
  }
}

I got a subject into which newly created objects are pushed. Several components subscribe on these and should react on different property changes.

In the above example if toObserve is set I want the component to do something. This works exactly once currently - Depending on the value the element has when it is registered with subject.next(element) the correct path is executed.

However as soon as I change the value of element.toObserve nothing is happening and the subscription seems to have no effect anymore.

Upvotes: 1

Views: 6482

Answers (3)

gabrielrincon
gabrielrincon

Reputation: 896

I do this, in this example I used a attribute type number, but, you can use another like "Test"

import { Observable, Subject, ReplaySubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CoinsService {

  private total: Subject<number> = new ReplaySubject<number>(1); //This is my attribute
  private total$ = this.total.asObservable(); //This is my observable

  constructor() {
    this.total.next(0); //Init my parameter
   }

  async add(coins: number) {
    // I must subscribe for take the value of attribute
    this.total$
      .pipe(
         take(1) // Guaranty that is the one time and release the subscription
      )
    .subscribe(async accumate => {
      this.total.next(accumate + coins);// Set the new value
    });
  }

  getTotal(): Observable<number> {
    return this.total$;//Return this observable for client subscription on every change
  }

}

That is.

I hope help you.

Upvotes: 0

Quentin Fonck
Quentin Fonck

Reputation: 1315

Doing a subscribe into a subscribe is not recommended. I would rather create an operators chain to your subject and subscribe to it:

If you want to perform some side effects in your components depending on a specific property in your stream, you can use the do operator:

interface Test {
  required: boolean;
  toObserve: boolean;
}

class TestClass implements OnInit {
  @Input() subject: Subject<Test>;

  ngOnInit() {
    this.registerHandlers().subscribe();
  }

  registerHandlers() {
    return this.subject
     .filter(element => element.required)
     .do(next => {
        if (next.toObserve) {
          // DO SOMETHING
        } else {
          // DO SOMETHING ELSE
        }
     });    
  }
}

Upvotes: 2

user6749601
user6749601

Reputation:

Sorry, but I reckon you didn't completely understand how subscription is to be done properly.

You have your subject

@Input() subject: Subject<Test>;

and you want to trigger actions whenever the subject changes. Then put this subscription into your ngOnInit()-method:

this.subject.subscribe(value => {
   // and here goes your evaluation
   if(value.toObserve) {
      // do something
   } else {
      // do something else
   }
});

and you can go even further and do something like this

this.subject.subscribe(value => {
   // and here goes your evaluation
   if(value.toObserve) {
      // do something
   } else {
      // do something else
   }

   if(value.required) {
      // do something
   } else {
      // do something else
   }
});

Upvotes: 1

Related Questions