Select only one row in mat-table and if select other one then unselect first one

voltdev picture voltdev · Jul 24, 2019 · Viewed 12k times · Source

I want to implement table with only one row selection. Now i have multiple selection.

I tried coupe ways to do this and i stayed by this one.

Graphic example: Graphic example

component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { UsersReadRepository } from '../../../../core/services';
import { MatTableDataSource } from '@angular/material';
import { User } from 'domain-models';
import { Observable, Subscription } from 'rxjs';
import { Subscribable } from 'rxjs/Observable';
import { SelectionModel } from '@angular/cdk/collections';

@Component({
    selector: 'choose-supervisior',
    templateUrl: './chooseSupervisior.component.html',
    styleUrls: ['./chooseSupervisior.component.scss']
})

export class ChooseSupervisiorComponent implements OnInit, OnDestroy {
    selectedRow: User;
    isLoading = true;
    dataSource: MatTableDataSource<User> = new MatTableDataSource();
    displayedColumns: string[] = ['name', 'surname', 'phone'];
    subscription$ : Subscription;

    constructor(public dialogRef: MatDialogRef<ChooseSupervisiorComponent>, private userReadRepository: UsersReadRepository) {
    }
    onCloseDialog(): void {
        this.dialogRef.close(this.selectedRow);
      }

    ngOnInit() {
        this.subscription$ = this.userReadRepository.getSupervisiorUsers()
        .subscribe(
            data => 
            {
                this.isLoading = false,
                this.dataSource.data = data;
            }
        )
    }
    highlight(highlighted: boolean) {
        highlighted = !highlighted;
      }

    getSupervisiorRecordFromTable(user: User){
        this.selectedRow = user;
    }

    ngOnDestroy() {
        this.subscription$.unsubscribe();
    }
}

component.html

<h2 mat-dialog-title>{{'insideChats.chooseSupervisiorHeader' | translate}}</h2>
<mat-divider></mat-divider>
<div mat-dialog-content>
    <mat-table #table [dataSource]="dataSource" class="mat-elevation-z8">
        <ng-container matColumnDef="name">
            <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
            <mat-cell *matCellDef="let user"> {{user.name}} </mat-cell>
        </ng-container>
        <ng-container matColumnDef="surname">
            <mat-header-cell *matHeaderCellDef> Surname </mat-header-cell>
            <mat-cell *matCellDef="let user"> {{user.surname}} </mat-cell>
        </ng-container>
        <ng-container matColumnDef="phone">
            <mat-header-cell *matHeaderCellDef> Phone </mat-header-cell>
            <mat-cell *matCellDef="let user"> {{user.phone}} </mat-cell>
        </ng-container>
        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;" 
        (click)="getSupervisiorRecordFromTable(row)"
        [ngClass]="{hovered: row.hovered, highlighted: row.highlighted}" (click)="row.highlighted = !row.highlighted" (mouseover)="row.hovered = true" (mouseout)="row.hovered = false"></mat-row >
    </mat-table>
    <mat-card class="loading-spinner" *ngIf="isLoading">
  <mat-progress-spinner 
    color="primary" 
    mode="indeterminate">
  </mat-progress-spinner>
</mat-card>
</div>
<mat-divider></mat-divider>
<div mat-dialog-actions>
    <button mat-dialog-close (click)="onCloseDialog()" mat-icon-button color="warn">
        <mat-icon>close</mat-icon>
    </button>
        <span class="buttons-spacer"></span>
    <button mat-button class="choose-button">{{'insideChats.chooseSupervisiorStartChat' | translate}}</button>
</div>

component.scss

.loading-spinner{
    display: flex; 
    justify-content: center; 
    align-items: center;
}

  .buttons-spacer {
    flex: 1 1 auto;
  }

  .mat-dialog-actions {
    justify-content: flex-end;
  }

  .basic-container {
    padding: 5px;
  }

  .mat-row.hovered {
    background: #eee;
  }

  .mat-row.highlighted {
    background: #999;
  }

  mat-cell.mat-cell, mat-header-cell.mat-header-cell {
    overflow: visible; 
  }

How to implement row selection with unsellecting the last one clicked selection and then this same with other clicking.

The point is just always available select only one row.

Answer

G. Tranter picture G. Tranter · Jul 24, 2019

Using a SelectionModel with multi-selection disabled will make things easier. See the example: https://material.angular.io/components/table/overview#selection.

Here's a modified version of the example on Stackblitz without the checkboxes and using single selection and some of your table's functionality: https://stackblitz.com/edit/angular-2yv8hk?file=app/table-selection-example.html.

In particular:

TS

export class TableSelectionExample {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
  selection = new SelectionModel<PeriodicElement>(false, []);
}

HTML

<mat-row *matRowDef="let row; columns: displayedColumns;" 
  (click)="selection.toggle(row)" 
  [ngClass]="{hovered: row.hovered, highlighted: selection.isSelected(row)}"
  (mouseover)="row.hovered = true" (mouseout)="row.hovered = false">
</mat-row>