skip to Main Content

I have getter in the component

here is it

     public get canSave(): boolean {
    const isValid = this.rows.every(r => r.phoneControl.valid);

    if (!isValid) {
      return false;
    }

    const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
    return changes.phones.changed || changes.emergencyPhone.changed;
  }

Then in the method onSubmitClick I need to update value of it

Here is how I try to do this

    public onSubmitClick(): void {
    const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
    this.canSave = false;

    this.params
      .onSubmit(changes)
      .pipe(take(1))
      .subscribe(() => {
        this.close(true).then();
      });
  }

But I get an error

Cannot assign to ‘canSave’ because it is a read-only property.

How can I update the value of canSave in onSubmitClick method?

Here is complete code of a component

    export class ManagePhonesPopup extends DialogBaseComponent<Params, boolean> implements OnInit {
  public override params!: Params;

  public rows: IPhoneRow[] = [];

  public get canSave(): boolean {
    const isValid = this.rows.every(r => r.phoneControl.valid);

    if (!isValid) {
      return false;
    }

    const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
    return changes.phones.changed || changes.emergencyPhone.changed;
  }

  constructor(
    dialog: DialogRef,
    confirmDialog: ConfirmDialogService,
    private readonly managePhonesPopupService: ManagePhonesPopupService,
  ) {
    super(dialog, confirmDialog);
  }

  public ngOnInit(): void {
    this.initRows(this.params.phones, this.params.emergencyPhone);
  }

  public onAddClick(): void {
    const newRow = this.managePhonesPopupService.createRowControls('', false);
    this.rows.push(newRow);
  }

  public onDeleteClick(row: IPhoneRow): void {
    this.rows = this.rows.filter(r => r != row);
  }

  public onCloseClick(): void {
    this.close().then();
  }

  public onSubmitClick(): void {
    const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
    this.canSave = false;

    this.params
      .onSubmit(changes)
      .pipe(take(1))
      .subscribe(() => {
        this.close(true).then();
      });
  }

  private initRows(phones: IEmployeeCellphone[], emergencyPhone?: string): void {
    const rows: IPhoneRow[] = phones.map(p => this.managePhonesPopupService.cellphoneToRowControls(p));

    if (!!emergencyPhone) {
      rows.push(this.managePhonesPopupService.emergencyPhoneToRowControls(emergencyPhone));
    }

    this.rows = rows;
  }

3

Answers


  1. As I understand it, you are looking for a way to force the value returned by canSave.

    To do so, you can add two additional private fields to your class:

      private _forcingCanSave = false;     // are we in a "forcing mode"?
      private _forcedCanSaveValue = false; // forced value to return
    

    Then, modify your existing logic like this:

      public get canSave(): boolean {
        if (this._forcingCanSave) return this._forcedCanSaveValue; // if in a "forcing mode", return the forced value; else continue with the existing logic
    
        const isValid = this.rows.every(r => r.phoneControl.valid);
    
        if (!isValid) {
          return false;
        }
    
        const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
        return changes.phones.changed || changes.emergencyPhone.changed;
      }
    

    And in order to enable the "forcing mode", you can create a new method:

      private forceCanSave(state: boolean) {
        this._forcingCanSave = true;
        this._forcedCanSaveValue = state;
      }
    

    This will enable the value override in canSave. You can then use it like this:

      public onSubmitClick(): void {
        const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
        this.forceCanSave(false); // force canSave to return false
    
        this.params
          .onSubmit(changes)
          .pipe(take(1))
          .subscribe(() => {
            this.close(true).then();
          });
      }
    

    Additionally, you can create a method to disable the "forcing mode", for example stopForcingCanSave() which will set this._forcingCanSave = false;. This will come in handy when you will want to stop forcing the value.

    Login or Signup to reply.
  2. Create a private _canSave property and updates it within the onSubmitClick method.

    export class ManagePhonesPopup extends DialogBaseComponent<Params, boolean> implements OnInit {
          public override params!: Params;
          public rows: IPhoneRow[] = [];
        
          private _canSave: boolean = false; // Private property for canSave
        
          public get canSave(): boolean {
            const isValid = this.rows.every(r => r.phoneControl.valid);
        if (this._canSave === false) {
          return false;
         }
            if (!isValid) {
              return false;
            }
        
            const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
            return this._canSave || changes.phones.changed || changes.emergencyPhone.changed;
          }
        
          constructor(
            dialog: DialogRef,
            confirmDialog: ConfirmDialogService,
            private readonly managePhonesPopupService: ManagePhonesPopupService,
          ) {
            super(dialog, confirmDialog);
          }
        
          public ngOnInit(): void {
            this.initRows(this.params.phones, this params.emergencyPhone);
          }
        
          public onAddClick(): void {
            const newRow = this.managePhonesPopupService.createRowControls('', false);
            this.rows.push(newRow);
          }
        
          public onDeleteClick(row: IPhoneRow): void {
            this.rows = this.rows.filter(r => r != row);
          }
        
          public onCloseClick(): void {
            this.close().then();
          }
        
          public onSubmitClick(): void {
            const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
            this._canSave = false; // Update the private property
        
            this.params
              .onSubmit(changes)
              .pipe(take(1))
              .subscribe(() => {
                this.close(true).then();
              });
          }
        
          private initRows(phones: IEmployeeCellphone[], emergencyPhone?: string): void {
            const rows: IPhoneRow[] = phones.map(p => this.managePhonesPopupService.cellphoneToRowControls(p));
        
            if (!!emergencyPhone) {
              rows.push(this.managePhonesPopupService.emergencyPhoneToRowControls(emergencyPhone));
            }
        
            this.rows = rows;
          }
        }
    
    Login or Signup to reply.
  3. In your code, canSave is a getter function, which means it’s a read-only property. But, you’re trying to assign a value to it, which is not allowed.

    Instead of assigning value to canSave, you should update the properties that canSave depends on. In your case, canSave depends on this.rows and this.params. Therefore, you should update these properties in your onSubmitClick method.

    Example;

    public onSubmitClick(): void {
     const changes = this.managePhonesPopupService.getChanges(this.rows, this.params);
     
     // Update the rows or params here
     // For example, if you want to set all rows as invalid, you can do:
     this.rows = this.rows.map(r => ({ ...r, phoneControl: { ...r.phoneControl, valid: false } }));
    
     this.params
       .onSubmit(changes)
       .pipe(take(1))
       .subscribe(() => {
         this.close(true).then();
       });
    }
    
    

    Updating this.rows to set all rows as invalid. You should replace this with the actual update you want to do.

    *The key here is to update the properties that canSave depends on, not canSave itself.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search