Classificação padrão em material angular - cabeçalho de classificação

89

Como posso alterar o código do Angular Material abaixo, para que a tabela de dados seja classificada pela coluna 'nome', em ordem crescente por padrão. A seta (indicando a direção da classificação atual) deve ser exibida.

Isso é o que eu quero alcançar:

insira a descrição da imagem aqui

Código original:

<table matSort (matSortChange)="sortData($event)">
  <tr>
    <th mat-sort-header="name">Dessert (100g)</th>
    <th mat-sort-header="calories">Calories</th>
    <th mat-sort-header="fat">Fat (g)</th>
    <th mat-sort-header="carbs">Carbs (g)</th>
    <th mat-sort-header="protein">Protein (g)</th>
  </tr>

  <tr *ngFor="let dessert of sortedData">
    <td>{{dessert.name}}</td>
    <td>{{dessert.calories}}</td>
    <td>{{dessert.fat}}</td>
    <td>{{dessert.carbs}}</td>
    <td>{{dessert.protein}}</td>
  </tr>
</table>

Eu estava tentando algo assim, mas não funciona (nenhuma seta exibida, não classificado)

<table matSort (matSortChange)="sortData($event)" matSortActive="name" matSortStart="asc" matSortDisableClear>

Aqui está o link para o Plunker

Jacek Kościesza
fonte
Pode ligar this.sortData({active: "name", direction: "asc"})para ngOnInitverificar o plunker
Pankaj Parkar
1
@PankajParkar Não é a solução correta. A tabela está classificada, mas o cabeçalho de classificação não sabe sobre ela e a seta (indicando a direção da classificação atual) não é exibida.
Jacek Kościesza

Respostas:

138

Você está confundindo matSortStartpara matSortDirection.

Experimente isto:

<table matSort (matSortChange)="sortData($event)" matSortActive="name" matSortDirection="asc" matSortDisableClear>

https://plnkr.co/edit/sg0hC5d8LTjLKhbH9Eug?p=preview

matSortStart pode ser usado para reverter o ciclo usado durante a classificação (por exemplo, quando o usuário clica para classificar, começa em desc em vez de asc).

Andrew Seguin
fonte
5
Este método funciona apenas pela primeira vez. Depois que a fonte de dados da tabela foi alterada, tento redefinir o matSortActivee, matSortDirectionmas a pequena seta não é exibida
Gil Epshtain
O exemplo parece não funcionar mais, fiz um novo: stackblitz.com/edit/angular-defaultsort?file=src/app/…
Ben
45

Você pode classificar a tabela programaticamente, invocando o sort(Sortable)método da fonte de dados. Supondo que você tenha uma dataSourcepropriedade de componente para a fonte de dados:

// to put next to the class fields of the component
@ViewChild(MatSort) sort: MatSort

// to put where you want the sort to be programmatically triggered, for example inside ngOnInit
this.sort.sort(({ id: 'name', start: 'asc'}) as MatSortable);
this.dataSource.sort = this.sort;
Nino Filiu
fonte
1
Isso é o que estou procurando, mas o único problema é que ele aciona o matSortChangeevento. Existe uma maneira de definir a classificação sem acionar o evento?
rain01
Não. É assim que o tipo é chamado. Por que você não deseja que o evento matSortChange seja acionado?
Nino Filiu
1
porque eu o defini para atualizar um cookie com asc/ descde uma coluna e se ele for chamado toda vez que a página for carregada, então sempre será diferente
rain01
17
@ViewChild(MatSort) sort: MatSort;

this.dataSource.sort = this.sort;

const sortState: Sort = {active: 'name', direction: 'desc'};
this.sort.active = sortState.active;
this.sort.direction = sortState.direction;
this.sort.sortChange.emit(sortState);

Deveria trabalhar. demo

E para mostrar a seta de direção de classificação, adicione o próximo css (solução alternativa)

th.mat-header-cell .mat-sort-header-container.mat-sort-header-sorted .mat-sort-header-arrow {
    opacity: 1 !important;
    transform: translateY(0) !important;
}
Aman Madiiarbekov
fonte
4
Forneça algumas explicações junto com seu código, para que o usuário posterior possa seguir suas idéias / código mais facilmente.
HansHirse
1
Usei a classificação do Nino e a solução alternativa CSS aqui para fazer com que minha classificação definida programaticamente mostrasse a seta.
bts
No angular 7, acabei de definir this.sort = {active: 'name', direction: 'desc'}; e não precisei adicionar nenhuma alteração de CSS para que a seta ficasse ativa.
Nick Gallimore
Nick Gallimore talvez você esteja adicionando seu css não no lugar correto? tente adicioná-lo em um arquivo css global principal (pode estar em assets / css / ... css)
Aman Madiiarbekov
10

Atualização de material (testado com v7.3):

@ViewChild(MatSort) matSort: MatSort;

private someMethod(): void {
  this.matSort.sort({ id: 'columnName', start: 'asc', disableClear: false });
}

Isto também irá atualizar a mat-sort-headerseta do sem qualquer solução alternativa

sschmid
fonte
3

Você também pode vincular propriedades de classificação de esteira a sua variável de componente.

Como @Andrew Seguin diz:

<table matSort matSortActive="name" matSortDirection="asc">

Esta é a maneira correta de definir a classificação padrão, se você souber qual é.

No caso de você conseguir classificar de outro lugar (no meu caso, de parâmetros de string de consulta), você também pode fazer assim (as setas de classificação funcionam perfeitamente aqui):

sortDirection: 'name',  // this can be changed or filled in any time
sortProperty: 'asc',


<mat-table matSort [matSortActive]="sortProperty" [matSortDirection]="sortDirection">
Milos
fonte
1

Talvez você tenha tentado chamar no init da página a função de classificação forçada no nome e na direção?

     ngOnInit() {
    let defSort: Sort = {};
    defSort.direction = 'asc';
    defSort.active = 'name';
    this.sortData(defSort);
  }
federico scamuzzi
fonte
6
Não é a solução correta. A tabela está classificada, mas o cabeçalho de classificação não sabe sobre ela e a seta (indicando a direção da classificação atual) não é exibida
Jacek Kościesza
1

No meu caso, a classificação não estava funcionando porque matColumDef id e mat-cell var são diferentes

<ng-container matColumnDef="firstName">
   <th mat-header-cell *matHeaderCellDef mat-sort-header class="mat-table-header">First Name</th>
  <td mat-cell *matCellDef="let item"> {{ item.name}}</td>
</ng-container>

depois de fazer alterações matColumnDef = "firstName" para matColumnDef = " name " que é o mesmo que o item. nome

    <ng-container matColumnDef="name">
   <th mat-header-cell *matHeaderCellDef mat-sort-header class="mat-table-header">First Name</th>
  <td mat-cell *matCellDef="let item"> {{ item.name}}</td>
</ng-container>

Isso funciona bem para mim

Yogesh Borkhade
fonte
0

Eu tive que fazer a classificação padrão no carregamento

const matSort = { id: defaultSort.name } as MatSortable;
this.sort.direction = defaultSort.sort === 'asc' ? '' : defaultSort.sort === 'desc' ? 'asc' : 'desc' as SortDirection;
this.sort.sort(matSort);
Illia
fonte
0

A resposta de @Andrew Seguin (primeira resposta aceita) fez o truque visual para mim, mas não classificou a tabela.

Minha solução é usar o código html fornecido por @Andrew Seguin e chamar o método sortData (sort: Sort) eu mesmo, mas como fazer isso? Conforme especificado na documentação , o ,, Sort '' é uma interface que possui duas propriedades, active e direction e a interface deve ser semelhante a esta:

export interface Sort {
   active:string //The id/name of the column being sorted
   direction:string //asc or dsc depending on the use case (The sort direction)
}

Portanto, o truque é chamar o método sortData (sort: Sort) em ngOnInit da seguinte maneira:

ngOnInit(){
    //Do some nitialization
    this.sortData({active:'name', direction:'asc'});
}

sortData(sort: Sort) {
    //Your sorting algorithm (see examples in documentation, link above and at the bottom)
}

O código HTML é como na resposta aceita ;-) Espero que isso ajude alguém, Alex

Exemplos de documentação

Alex B
fonte
0

Existem vários fatores contribuintes que afetam o comportamento. Principalmente é o uso de MatTableDataSource em vez de um derivado feito à mão de DataSource . Portanto, soluções diferentes podem funcionar em alguns casos e não em outros.

De qualquer forma, é um bug antigo que foi bem coberto no GitHub . Vote a favor desse problema do GitHub para atrair a atenção da equipe Angular.

A solução mais durável publicada nesse thread do GitHub ( link ) é chamar o seguinte método ao aplicar uma ordem de classificação:

public setSort(id: string, start?: 'asc' | 'desc') {
    start = start || 'asc';
    const matSort = this.dataSource.sort;
    const toState = 'active';
    const disableClear = false;

    //reset state so that start is the first sort direction that you will see
    matSort.sort({ id: null, start, disableClear });
    matSort.sort({ id, start, disableClear });

    //ugly hack
    (matSort.sortables.get(id) as MatSortHeader)._setAnimationTransitionState({ toState });
}
Alex Klaus
fonte