es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Error de redimensionamiento de tabla angular mat en ordenación mat

Aquí en mat table se usa resizeColumn para cambiar el tamaño de las columnas de la tabla. Puedo cambiar el tamaño para dos columnas, Annotation y status, porque estas columnas no tienen encabezado de ordenamiento, pero para uploadTime y size aquí no funciona resizeColumn, cuando elimino mat-sort-header comienza a funcionar. No puedo encontrar el problema. ¿Cómo puedo cambiar el tamaño con mat-sort-header?

<table mat-table="" [datasource]="dataSource" matsort="" (matsortchange)="sortChange($event)" class="mat-elevation-z8">
        <ng-container matcolumndef="annotation">
            <th mat-header-cell="" *matheadercelldef="" [resizecolumn]="true">Annotation</th>
            <td mat-cell="" *matcelldef="let data;let i=index">{{data.annotation}}</td>
        </ng-container>
        <ng-container matcolumndef="status">
            <th mat-header-cell="" *matheadercelldef="" [resizecolumn]="true">Status</th>
            <td mat-cell="" *matcelldef="let data;let i=index">{{data.status}}</td>
        </ng-container>
        <ng-container matcolumndef="uploadTime">
            <th mat-header-cell="" *matheadercelldef="" [resizecolumn]="true" mat-sort-header="">UploadTime</th>
            <td mat-cell="" *matcelldef="let data;let i=index">{{data.uploadedTime}}</td>
        </ng-container>
        <ng-container matcolumndef="size">
            <th mat-header-cell="" *matheadercelldef="" [resizecolumn]="true" mat-sort-header="">Size</th>
            <td mat-cell="" *matcelldef="let data;let i=index">{{data.size}}</td>
        </ng-container>
        <tr mat-header-row="" *matheaderrowdef="displayColumns"></tr>
        <tr mat-row="" *matrowdef="let row;columns:displayColumns | paginate: {itemsPerPage: 
          itemsPerPage, currentPage: p,totalItems:size}"></tr>
    </table>

Directiva ResizeColumn

import { Directive,OnInit, Renderer2, Input, ElementRef,ViewChild} from '@angular/core';
import { MatSort } from '@angular/material/sort';

@Directive({
  selector: '[resizeColumn]'
})
export class ResizecolDirective implements OnInit {

@Input("resizeColumn") resizable!:boolean;
  private startX!:number;
  private startWidth!:number;
  private column!: HTMLElement;

  private table!: HTMLElement;

  private pressed!: boolean;

  constructor(private renderer: Renderer2, private el: ElementRef) { 
    this.column = this.el.nativeElement;
  }
  ngOnInit(){
    if (this.resizable) {
      const row = this.renderer.parentNode(this.column);
      const thead = this.renderer.parentNode(row);
      this.table = this.renderer.parentNode(thead);
      const resizer = this.renderer.createElement("span");
      this.renderer.addClass(resizer, "resize-holder");
      this.renderer.appendChild(this.column, resizer);
      this.renderer.listen(resizer, "mousedown", this.onMouseDown);
      this.renderer.listen(this.table, "mousemove", this.onMouseMove);
      this.renderer.listen("document", "mouseup", this.onMouseUp);
    }
  }
  onMouseDown = (event: MouseEvent) => {
    this.pressed = true;
    this.startX = event.pageX;
    this.startWidth = this.column.offsetWidth;
  };

  onMouseMove = (event: MouseEvent) => {
    const offset = 30;
    if (this.pressed && event.buttons) {
      this.renderer.addClass(this.table, "resizing");
      let width =this.startWidth + (event.pageX - this.startX - offset);
      this.renderer.setStyle(this.column, "width", `${width}px`);
    }
  };

  onMouseUp = (event: MouseEvent) => {
    if (this.pressed) {
      this.pressed = false;
      this.renderer.removeClass(this.table, "resizing");
    }
  };

}
Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema al cambiar el tamaño de las columnas con mat-sort-header es que al hacer clic en el encabezado de clasificación se activa la ordenación de la tabla y no el cambio del tamaño de la columna. Para resolver este problema, puedes desactivar el comportamiento de ordenación mientras se cambia el tamaño de la columna y restaurarlo después de que se haya completado el cambio de tamaño.

    Para hacer esto, puedes añadir una bandera sortingDisabled a tu ResizecolDirective y establecerla en true cuando el usuario empiece a cambiar el tamaño de la columna. Luego, puedes desactivar la ordenación en el objeto MatSort estableciendo su propiedad disableClear en true. Esto evitará que la columna se ordene mientras se está cambiando el tamaño. Una vez que se completa el cambio de tamaño, puedes restaurar el comportamiento de ordenamiento estableciendo disableClear de nuevo en false.

    Aquí tienes la ResizecolDirective modificada:

    import { Directive, OnInit, Renderer2, Input, ElementRef } from '@angular/core';
    import { MatSort } from '@angular/material/sort';
    
    @Directive({
      selector: '[resizeColumn]',
    })
    export class ResizecolDirective implements OnInit {
      @Input('resizeColumn') resizable!: boolean;
    
      private startX!: number;
      private startWidth!: number;
      private column!: HTMLElement;
    
      private table!: HTMLElement;
      private sortingDisabled = false;
    
      constructor(
        private renderer: Renderer2,
        private el: ElementRef,
        private matSort: MatSort // inyectar MatSort
      ) {
        this.column = this.el.nativeElement;
      }
    
      ngOnInit() {
        if (this.resizable) {
          const row = this.renderer.parentNode(this.column);
          const thead = this.renderer.parentNode(row);
          this.table = this.renderer.parentNode(thead);
          const resizer = this.renderer.createElement('span');
          this.renderer.addClass(resizer, 'resize-holder');
          this.renderer.appendChild(this.column, resizer);
          this.renderer.listen(resizer, 'mousedown', this.onMouseDown);
          this.renderer.listen(this.table, 'mousemove', this.onMouseMove);
          this.renderer.listen('document', 'mouseup', this.onMouseUp);
        }
      }
    
      onMouseDown = (event: MouseEvent) => {
        this.sortingDisabled = true; // desactivar ordenación durante el cambio de tamaño
        this.matSort.disableClear = true; // desactivar ordenación
        document.body.style.cursor = 'col-resize'; // cambiar cursor
        this.startX = event.pageX;
        this.startWidth = this.column.offsetWidth;
      };
    
      onMouseMove = (event: MouseEvent) => {
        const offset = 30;
        if (this.sortingDisabled && event.buttons) {
          this.renderer.addClass(this.table, 'resizing');
          let width = this.startWidth + (event.pageX - this.startX - offset);
          this.renderer.setStyle(this.column, 'width', `${width}px`);
        }
      };
    
      onMouseUp = (event: MouseEvent) => {
        if (this.sortingDisabled) {
          this.sortingDisabled = false; // habilitar ordenación después del cambio de tamaño
          this.matSort.disableClear = false; // habilitar ordenación
          document.body.style.cursor = 'auto'; // restaurar cursor
          this.renderer.removeClass(this.table, 'resizing');
        }
      };
    }
    

    Al desactivar la ordenación mientras se cambia el tamaño, te aseguras de que los comportamientos de redimensionamiento y ordenación de la columna no entren en conflicto entre sí.

Comments are closed.