Sergiu Molnar
Sergiu Molnar

Reputation: 1020

Mat-checkbox checked property determined by modal response

I have an array of users and in HTML I used *ngFor to generate a checkbox for each element. I also have an @Input assignedAccountIds[] which represents the default selected users.

The checkbox element is the following one:

<mat-checkbox
   color="primary"
   [disabled]="disableCurrentAccountCheckbox && account.id === currentAccountId"
   [checked]="isAccountSelected(account)"
   (change)="onSelectAccount($event, account)"
>

isAccountSelected method verify if a user exists in the selected items array to know if I need to check it or not, and here is the implementation:

isAccountSelected(account: ClientAccount): boolean {
    return (this.assignedAccountIds || []).includes(account.id);
}

On the change output, the method implementation is the following one:

onSelectAccount(event: MatCheckboxChange, account: ClientAccount): void {
    if (
      !event.checked &&
      this.currentAccountId &&
      account.id === this.currentAccountId
    ) {
      const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
        data: {
          message: `You will not be able to see this inspection if you unassign yourself!`,
          buttonColor: 'primary',
          buttonLabel: 'Unassign',
        },
        position: {
          right: '10px',
          bottom: '10px',
        },
        maxWidth: '580px',
      });

      dialogRef
        .afterClosed()
        .pipe(untilDestroyed(this))
        .subscribe(result => console.log(result));
    } else {
      this.selectionChange.emit({ id: account.id, checked: event.checked });
    }
  }

So, what I'm actually trying to do is to display a confirmation modal when you want to unselect yourself from the list. And only after you select Yes or No from the modal, the checkbox will remain checked or will be unchecked.

Upvotes: 0

Views: 3115

Answers (2)

jhthompson
jhthompson

Reputation: 316

As of v15, the best way I've found to do this is to provide a 'noop' MAT_CHECKBOX_DEFAULT_OPTIONS to override the default click behavior:

Component:

@Component({
    selector: 'app-checkbox-component',
    templateUrl: './app-checkbox.component.html',
    styleUrls: ['./app-checkbox.component.scss'],
    providers: [
        { provide: MAT_CHECKBOX_DEFAULT_OPTIONS, useValue: { clickAction: 'noop' } as MatCheckboxDefaultOptions },
    ],
})
export class InlineHardCopyDeliveredEventComponent {
    isCheckboxChecked = false;

    constructor(private dialog: MatDialog) {}

    openModal(): void {
        this.dialog
            .open()
            .afterClosed()
            .subscribe((result) => {
                this.isCheckboxChecked = result;
            });
    }
}

Template

<mat-checkbox
    (click)="openModal()"
    [checked]="isCheckboxChecked"
></mat-checkbox>

Upvotes: 0

G. Tranter
G. Tranter

Reputation: 17958

MatCheckbox does not provide a built-in way to "intercept" a check/uncheck action. You can only listen to the change event after it happens. However, you can use an ordinary click event to do the intercepting:

Checkbox

<mat-checkbox #cb (click)="confirmAssign($event)">Assigned</mat-checkbox>

Dialog actions

<mat-dialog-actions>
  <button mat-button [mat-dialog-close]="false">Cancel</button>
  <button mat-button [mat-dialog-close]="true">Unassign</button>
</mat-dialog-actions>

TS

@ViewChild('cb', {static: true}) cb: MatCheckbox;

constructor(public dialog: MatDialog) {}

confirmAssign(event) {

  // only intercept if currently checked
  if (this.cb.checked) {

    // stop the click from unchecking the checkbox
    event.preventDefault();

    // ask for confirmation
    this.dialog.open(ConfirmationDialogComponent).afterClosed().subscribe(confirmed => {
      if (confirmed) {
        // uncheck the checkbox
        setTimeout(() => this.cb.checked = false);
      }
    });
  }
}

Upvotes: 3

Related Questions