Home > other >  How do I combine two subscriptions in Angular?
How do I combine two subscriptions in Angular?

Time:05-10

Is there a way to combine the subscriptions for this.controls.attendanceDate and this.controls.type? I need to have access to both at the same time in order to call each of this.isAttendanceDateOnOrAfterStartDate() and this.isAttendanceDuplicate() at the same time in the if statement.

 onAttendanceFormChanges(): void {
    this.subscriptions.push(this.controls.attendanceDate.valueChanges.subscribe(() => {     
      this.subscriptions.push(this.$spService.clientProfile$.subscribe(client => {
        if (this.controls.attendanceDate.value) {
            if (this.isAttendanceDateOnOrAfterStartDate(this.controls.attendanceDate.value, client)) {
              this.isValidAttendanceDate$.next(false);
              this.controls.attendanceDate.setErrors(null);
              this.controls.status.enable();
          } else {
            this.isValidAttendanceDate$.next(true);
            this.controls.attendanceDate.setErrors({ 'duplicate': true });
            this.controls.status.disable();
          }
        }
      }));
    }));
    this.subscriptions.push(this.controls.type.valueChanges.subscribe(() => {
      this.subscriptions.push(this.$spService.clientAttendance$.subscribe(attendances => {
        if (this.controls.attendanceDate.value) {
            if (this.isAttendanceDuplicate(this.controls.attendanceDate.value, this.controls.type.value.id, attendances)) {
            this.isDuplicateAttendance$.next(true);
            this.controls.attendanceDate.setErrors({ 'duplicate': true });
            this.controls.status.disable();
          } else {
            this.isDuplicateAttendance$.next(false);
            this.controls.attendanceDate.setErrors(null);
            this.controls.status.enable();
          }
        }
      }));
   }));

CodePudding user response:

Use merge operator to combine multiple subscriptions. See the example https://www.learnrxjs.io/learn-rxjs/operators/combination/merge

merge(this.controls.attendanceDate.valueChanges, this.controls.type.valueChanges)
            .subscribe((data) => {
                // Do your stuff here
            });

CodePudding user response:

Avoid subscribing inside subscribe. Use composability of rxjs to avoid subscription inside subscription. You can rewrite your observables like this -

    onAttendanceFormChanges(): void {

  const attendanceDateValueChanges$ = 
      this.controls.attendanceDate.valueChanges.pipe(
        mergeMap(() => {
          return this.$spService.clientProfile$;
        }),
        tap(client => {
          if (this.controls.attendanceDate.value) {
            if (this.isAttendanceDateOnOrAfterStartDate(this.controls.attendanceDate.value, client)) {
              this.isValidAttendanceDate$.next(false);
              this.controls.attendanceDate.setErrors(null);
              this.controls.status.enable();
            } else {
              this.isValidAttendanceDate$.next(true);
              this.controls.attendanceDate.setErrors({ 'duplicate': true });
              this.controls.status.disable();
            }
          }
        })
      )


  const typeValueChanges$ = 
        this.controls.type.valueChanges.pipe(
          mergeMap(() => {
            return this.$spService.clientAttendance$;
          }),
          tap((attendances) => {
            if (this.controls.attendanceDate.value) {
              if (this.isAttendanceDuplicate(this.controls.attendanceDate.value, this.controls.type.value.id, attendances)) {
                this.isDuplicateAttendance$.next(true);
                this.controls.attendanceDate.setErrors({ 'duplicate': true });
                this.controls.status.disable();
              } else {
                this.isDuplicateAttendance$.next(false);
                this.controls.attendanceDate.setErrors(null);
                this.controls.status.enable();
              }
            }
          })
        );

    merge(attendanceDateValueChanges$, typeValueChanges$).subscribe();
 }));

Since you have not posted much details about 'what is your meaning by combine' - So I have used merge operator. You could also use combineLatest OR zip depends on what your need is. Google about these operators to combine your observables. Hope it helps.

  • Related