the button does not coming back into original state when subcribe completed

27 Views Asked by At

I am passing from parent an object array which includes a button inside, in this button I have 2 properties, enable and disable the button, and one more to execute a function, the button works fine, when I click the button become disabled, while the request is executing, but once it is finished, it is not enabled again, despite the fact that the this.loading property is false again.

// parent-component.ts
private initForm() {
    this.jsonForm = {
      controls: [
        {
          /// code
        },
        {
          type: 'button',
          label: 'Send',
          disabled: () => this.handleLoading(),
          action: (formValue) => this.onSubmit(formValue)
        }
      ]
    }
  }

  handleLoading(): boolean {
    return this.loading
  }


  onSubmit(formValue) {
    this.loading = true
    this.auth.login(formValue)
      .subscribe(
        () => {
          this.loading = false
        },
        err => {
          this.loading = false
          console.log('eror', err)
        }
      )
  }
// parent-component.html
<DynamicForm [jsonForm]="jsonForm"></DynamicForm> 
// child-component.html
 <ng-container *ngFor="let control of jsonForm?.controls">
            <ng-container *ngIf="control.type==='button'">
                <UIButton 
                    (click)="control.action(myForm.value)"
                    [disabled]="control.disabled()">
                        <span *ngIf="!control.disabled()">{{control.label}} <i *ngIf="icon" class="{{icon}} mr-1"></i></span>
                        <span class="blink" *ngIf="control.disabled()">Wait <i class="fa fa-spinner fa-spin"></i></span>
                </UIButton>
            </ng-container>
</ng-container>
1

There are 1 best solutions below

0
misha130 On

Because Angular can't actually detect changes in primitive values.

For example this.loading in the beginning is true, so angular takes the reference of "true" and checks if true changes. True always stays true because you replace it with a completely different value that is "false". Angular can't detect this. Same goes for integers, it can't detect that a 1 has been changed to 0 because it checks it as an object reference not as a value

You need to create a field called:

public loading$: BehaviorSubject = new BehaviorSubject(false);

Then switch in the disabled property (removing handleLoading):

disabled: this.loading$,

Whenever you want to switch values you use:

this.loading$.next(true);
this.loading$.next(false);

and the UI Button should use the async pipe

  <UIButton [disabled]="control.disabled | async">