Search code examples
angulartypescriptrxjsemit

Send data to different component with angular emit


There is a button that calculates desi on the product editing page. When this button is clicked, a different component, the modal, opens. In the opened modal, desi calculation is made by taking the necessary information. When I printed this information received from the user to the console on the product editing page, the gravity value was written as length. I researched but couldn't find the reason. The emit structure I created was a bit long. Can you give me suggestions for writing a shorter and cleaner code?

I tried to send the data in a single emit but I got an error because the emit received only one data.

modal component:


  @Output() dimensionalWeightCalculated: EventEmitter<number> = new EventEmitter();
  @Output() width: EventEmitter<number> = new EventEmitter();
  @Output() length: EventEmitter<number> = new EventEmitter();
  @Output() gravity: EventEmitter<number> = new EventEmitter();
  @Output() height: EventEmitter<number> = new EventEmitter();

...

 calculateDesi(): void {
    this.submitted = true;

    if (this.desiForm.valid) {
      const { length, width, height, gravity } = this.desiForm.value;
      const dimensionalWeight = gravity ? parseFloat(gravity) : (length * width * height) / 3000;
  
      this.dimensionalWeightCalculated.emit(dimensionalWeight); // Sadece tek bir değer yayınlayın
      this.length.emit(length);
      this.length.emit(gravity);
      console.log(gravity)
      this.width.emit(width);
      this.height.emit(height);
  
      this.modalService.dismissAll();
    }
  }

product edit component:

openDimensionalWeightCalculator(): void {
    const modalRef = this.modalService.open(DimensionalWeightCalculatorComponent, { centered: true, size: 'lg' });

    modalRef.componentInstance.dimensionalWeightCalculated.subscribe((dimensionalWeight: number) => {
      console.log('Calculated dimensional weight:', dimensionalWeight);
      this.productEditForm.get('ProductDetail')?.get('dimensional_weight')?.setValue(dimensionalWeight.toString());
      modalRef.close();
    });

    modalRef.componentInstance.length.subscribe((length: number) => {
      console.log('length:', length);
      this.productEditForm.get('ProductDetail')?.get('length')?.setValue(length.toString());
      modalRef.close();
    });

    modalRef.componentInstance.gravity.subscribe((gravity: number) => {
      console.log('gravity:', gravity);
      this.productEditForm.get('ProductDetail')?.get('weight')?.setValue(gravity.toString());
      modalRef.close();
    });

    modalRef.componentInstance.width.subscribe((width: number) => {
      console.log('width:', width);
      this.productEditForm.get('ProductDetail')?.get('width')?.setValue(width.toString());
      modalRef.close();
    });

    modalRef.componentInstance.height.subscribe((height: number) => {
      console.log('height:', height);
      this.productEditForm.get('ProductDetail')?.get('height')?.setValue(height.toString());
      modalRef.close();
    });
  }
}

current console output:

  • Calculated dimensional weight: 4
  • length: 1
  • length: 4
  • 4
  • width: 2
  • height: 3

Solution

  • We can use combineLatest from rxjs to get all the values simultaneously.

    openDimensionalWeightCalculator(): void {
        const modalRef = this.modalService.open(DimensionalWeightCalculatorComponent, { centered: true, size: 'lg' });
        combineLatest(
           modalRef.componentInstance.dimensionalWeightCalculated,
           modalRef.componentInstance.length,
           modalRef.componentInstance.gravity,
           modalRef.componentInstance.width,
           modalRef.componentInstance.height,
        ).subscribe(([
           dimensional_weight,
           length, 
           gravity, 
           width, 
           height
          ]: Array<any>) => {
              const ProductDetailCtrl = this.productEditForm.get('ProductDetail');
              if(ProductDetailCtrl) {
                   const patchValueObj = {
                       dimensional_weight,
                       length, 
                       gravity, 
                       width, 
                       height 
                   };
                   // remove all undefined and falsy values except zero
                   const result = {};
                   const patchValueObjFiltered = Object.keys(object).forEach(k => (object[k] || object[k] === 0) && (result[k] = object[k]));
                   
                   ProductDetailCtrl.patchValue(result);
              }
              modalRef.close();
        });
    }