dimanche 6 décembre 2020

Angular Material table filter uncheck selected rows

i'm developing an angular project that has a table with filterPredicate function and every row has a mat-checkbox on it to have a multiple selection of the rows and do another stuff later.

The problem starts when i check one or many rows and then i want to use the filter to get another row: the checked rows before changes it's state to "unchecked".

this is the html:

<mat-card class="titulo">
    <mat-card-header>
        <mat-card-title style="line-height:60px;">Modificación múltiple de procesos</mat-card-title>
    </mat-card-header>
    <br>
</mat-card>

<!-- <mat-form-field id="filtro" appearance="outline">
    <mat-label>Filtrar</mat-label>
    <input matInput (keyup)="applyFilter($event)">
</mat-form-field> -->

<!-- FILTERS -->
<div style="padding-top:30px">
      
    <form [formGroup]="form" class="search__form">
      <mat-form-field class="search__form_field" appearance="outline">
        <mat-label>OT</mat-label>
        <input type="number"
              
              matInput
              formControlName="oTe"
              (keyup)="applyFilter()"
        >
      </mat-form-field>
      <mat-form-field class="search__form_field" appearance="outline">
        <mat-label>OP</mat-label>
        <input type="number"
              
              matInput
              formControlName="oPe"
              (keyup)="applyFilter()"
        >
      </mat-form-field>
      <mat-form-field class="search__form_field" appearance="outline">
        <mat-label>Rango</mat-label>
        <input type="number"
              
              matInput
              formControlName="rangoInicio"
              (keyup)="applyFilter()"
        >
      </mat-form-field>
      
      <mat-form-field class="search__form_field" appearance="outline">
        <mat-label>Potencia</mat-label>
        <input type="number"
              
              matInput
              formControlName="potencia"
              (keyup)="applyFilter()"
        >
      </mat-form-field>
      <mat-form-field class="search__form_field" appearance="outline">
        <mat-label>Cliente</mat-label>
        <input type="text"
              
              matInput
              formControlName="nombreCli"
              (keyup)="applyFilter()"
        >
      </mat-form-field>
      <button mat-icon-button (click)="clean()" color="primary" aria-label="Example icon button with a delete icon">
        <mat-icon>backspace</mat-icon>
      </button>
      <mat-form-field appearance="outline" *ngIf="showButtons==true">
        <mat-label>Procesos</mat-label>
        <mat-select [formControl]="etapas" multiple>
          <mat-option *ngFor="let etapa of dataTipoEtapa" [value]="etapa"></mat-option>
        </mat-select>
      </mat-form-field>
      <button mat-flat-button style="background-color:cadetblue;color:white;" *ngIf="showButtons==true" (click)="etapasChecked()">Asignar Procesos Seleccionados</button>

    </form>

</div>

<!--TABLE-->
<div id="tabla1" class="mat-elevation-z8">
    <div class="example-loading-shade" *ngIf="isLoadingResults">
        <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
    </div>
    <table mat-table id="tabla1" [dataSource]="data" > 
        <ng-container matColumnDef="select" >
            <th mat-header-cell *matHeaderCellDef style="text-align: center;">
              <!-- <mat-checkbox (change)="$event ? masterToggle() : null"
                            [checked]="selection.hasValue() && isAllSelected()"
                            [indeterminate]="selection.hasValue() && !isAllSelected()"
                            [aria-label]="checkboxLabel()"> 
              </mat-checkbox>-->
            </th>
            <td mat-cell *matCellDef="let row">
              <mat-checkbox (click)="$event.stopPropagation()"
                            (change)="$event ? checkedValue(row,$event) : null"
                            [checked]="selection.isSelected(row)"
                            [aria-label]="checkboxLabel(row)">
              </mat-checkbox>
            </td>
        </ng-container>
        
          
          <ng-container matColumnDef="oP" sticky>
            <th mat-header-cell *matHeaderCellDef style="text-align: center;">oP</th>
            <td mat-cell *matCellDef="let row"></td>
          </ng-container>
  
           
          <ng-container matColumnDef="oT" sticky>
            <th mat-header-cell *matHeaderCellDef style="text-align: center;">oT</th>
            <td mat-cell *matCellDef="let row"></td>
          </ng-container>
  
          <ng-container matColumnDef="rango" sticky>
            <th mat-header-cell *matHeaderCellDef style="text-align: center;">rango</th>
            <td mat-cell *matCellDef="let row"></td>
          </ng-container>

          <ng-container matColumnDef="Cliente" sticky>
            <th mat-header-cell *matHeaderCellDef style="text-align: center;">Cliente</th>
            <td mat-cell *matCellDef="let row"></td>
          </ng-container>

          <ng-container matColumnDef="Potencia" sticky> 
            <th mat-header-cell *matHeaderCellDef  style="text-align: center;">Potencia</th>
            <td mat-cell *matCellDef="let row" ></td>
          </ng-container>
  
          <ng-container matColumnDef="Observaciones" sticky>
            <th mat-header-cell *matHeaderCellDef style="text-align: center;">Observaciones</th>
            <td mat-cell *matCellDef="let row"></td>
          </ng-container>
        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>    
    </table>
</div>
<mat-paginator [pageSizeOptions]="[30, 50, 100]"></mat-paginator>

This is the ts file:

@Component({
  selector: 'app-varios-procesos',
  templateUrl: './varios-procesos.component.html',
  styleUrls: ['./varios-procesos.component.css']
})
export class VariosProcesosComponent implements OnInit {
  data:MatTableDataSource<Transformadores>;
  dataTipoEtapa:TipoEtapa[]=[];
  isLoadingResults = true;
  etapas=new FormControl();
  displayedColumns:string[]=['select','oT','oP','rango','Cliente','Potencia','Observaciones']
  showButtons=false;
  
  //Variables para los filtros
  form=new FormGroup(
    {
      oTe:new FormControl(),    
      nucleos:new FormControl(),
      oPe   :new FormControl(),
      rangoInicio   :new FormControl(),
      rangoFin:new FormControl(),   
      observaciones:new FormControl(),  
      potencia  :new FormControl(),
      nombreCli :new FormControl(),
    }
  )
  oTe= '';
  oPe= '';
  rangoInicio= '';
  potencia= '';
  nombreCli= '';
  
  //array con los tranformadores elegidos
  arrTrafoSelected:Transformadores[]=[];

  @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
  @ViewChild(MatSort, {static: true}) sort: MatSort;


  constructor(private transformadoresService: TransformadoresService,private tipoEtapaService:TipoEtapaService,public dialog: MatDialog) { }
  
  
  ngOnInit(): void {
    this.data=new MatTableDataSource();
    this.data.filterPredicate =this.createFilter();

    this.getTransformadores();
    this.getTipoEtapas();
  }
  
  selection = new SelectionModel<Transformadores>(true, []);

  getTransformadores(): void {
    this.transformadoresService.getTransformadores()
      .subscribe(transfo => {
        this.data.data = transfo;
        this.data.paginator = this.paginator;
        this.data.sort = this.sort;

        this.isLoadingResults = false;
      }, err => {
        // console.log(err);
        this.isLoadingResults = false;
      });
      
  }

  getTipoEtapas():void{
    this.tipoEtapaService.getTipoEtapas().subscribe(tipoEtapas=>{
      this.dataTipoEtapa=tipoEtapas;
    })
  }

  /** Whether the number of selected elements matches the total number of rows. */
  isAllSelected() {
    if(this.data!=undefined)
    {
      const numSelected = this.selection.selected.length;
      const numRows = this.data.data.length;
      return numSelected === numRows;
    }
    else{
      return false;
    }
  }

  /** Selects all rows if they are not all selected; otherwise clear selection. */
  masterToggle() {
    
    this.isAllSelected() ?
        this.selectionClear() : 
        this.data.data.forEach(row => {
            let mcc=new MatCheckboxChange();
            mcc.checked=true;

            this.selection.select(row);
            this.checkedValue(row,mcc);
          }
        );
        
  }

  selectionClear(){
    this.selection.clear();
    this.showButtons=false;
  }

  /** The label for the checkbox on the passed row */
  checkboxLabel(row?: Transformadores): string {
    if (!row) {
      return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
    }
    
    return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.idTransfo}`;
  }

  checkedValue(row,event){
    //this.selection.toggle(event);
    
    var i = 0;
    while (i < this.arrTrafoSelected.length) {
      console.log(this.arrTrafoSelected)
      if (this.arrTrafoSelected[i] === row) {
        console.log(this.arrTrafoSelected);
        this.arrTrafoSelected.splice(i, 1);
      } else {
        ++i;
      }
    }
    if(event.checked==true )
    {
      this.showButtons=true;
      this.arrTrafoSelected.push(row);
    }
    else{
      let j=this.arrTrafoSelected.indexOf(row);
      if(j>-1)
      {
        this.arrTrafoSelected.splice(j,1);
      }
      if(this.arrTrafoSelected.length==0)
      {
        this.showButtons=false;
      }
    }
    console.log(this.arrTrafoSelected);
  }

...

createFilter() {
    return (row:any, filters: string) => {
      
      // split string per '$' to array
      console.log("Filters",filters);
      
      const filterArray = filters.split('$');
      
      const oTe = filterArray[0];
      const oPe = filterArray[1];
      const rangoInicio = filterArray[2];
      const potencia = filterArray[3];
      const nombreCli = filterArray[4];

      const matchFilter = [];

      // // Fetch data from row
      if(row.hasOwnProperty('oTe'))
      {
        const columnOTe = row.oTe==null ? '' : row.oTe;
        const columnOPe = row.oPe==null ? '' : row.oPe;
        const columnRangoInicio = row.rangoInicio==null ? '' : row.rangoInicio;
        const columnPotencia = row.potencia==null ? '' : row.potencia;
        const columnNombreCli = row.nombreCli == null ? '' : row.nombreCli;
        
        

        //verify fetching data by our searching values
        const customFilterOTe =  columnOTe.toString().includes(oTe);
        const customFilterOPe = columnOPe.toString().includes(oPe);
        const customFilterRangoInicio =  columnRangoInicio.toString().includes(rangoInicio);
        const customFilterPotencia =  columnPotencia.toString().includes(potencia);
        const customFilterNombreCli = columnNombreCli.toString().toLowerCase().includes(nombreCli);
        
        // //push boolean values into array
        matchFilter.push(customFilterOTe);
        matchFilter.push(customFilterOPe);
        matchFilter.push(customFilterRangoInicio);
        matchFilter.push(customFilterPotencia);
        matchFilter.push(customFilterNombreCli);
      }
      // else{
      //   return false;
      // }



      // return true if all values in array is true
      // else return false
      return matchFilter.every(Boolean);
    };
  }

  applyFilter() {
    
    const ot =this.form.get('oTe').value;
    const op=this.form.get('oPe').value;
    const rI=this.form.get('rangoInicio').value;
    const pot=this.form.get('potencia').value;
    const nC=this.form.get('nombreCli').value;

    this.oTe = ot === null ? '' : ot;
    this.oPe = op === null ? '' : op;
    this.rangoInicio = rI === null ? '' : rI;
    this.potencia = pot === null ? '' : pot;
    this.nombreCli = nC === null ? '' : nC;

    // create string of our searching values and split if by '$'
    const filterValue = this.oTe + '$' + this.oPe+'$' + this.rangoInicio+'$' + this.potencia+'$' + this.nombreCli;
    
    this.data.filter = filterValue.trim().toLowerCase();
  }

  clean(){
    this.form.reset();
    this.data.filter='';
  }

}

So, my question is ¿how to keep the rows checked?

Thanks in advice!




Aucun commentaire:

Enregistrer un commentaire