Я пытаюсь заставить mat-table
сортировку работать локально, и хотя я могу заставить данные отображаться должным образом, нажатие на строку заголовка не приводит к сортировке, как в онлайн-примерах (вообще ничего не происходит). Я пытаюсь заставить эту демонстрацию работать локально:
https://material.angular.io/components/sort/overview
https://plnkr.co/edit/XF5VxOSEBxMTd9Yb3ZLA?p=preview
Я создал новый проект с Angular CLI, а затем выполнил следующие шаги: https://material.angular.io/guide/getting-started
Вот мои локальные файлы:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MatSort, MatTableModule } from '@angular/material';
import { AppComponent } from './app.component';
import { TableSortingExample } from './table-sorting-example';
@NgModule({
declarations: [
AppComponent,
TableSortingExample,
MatSort
],
imports: [
BrowserModule,
MatTableModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
}
app.component.html
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
<table-sorting-example></table-sorting-example>
</div>
таблица-сортировка-example.html
<div class="example-container mat-elevation-z8">
<mat-table #table [dataSource]="dataSource" matSort>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- ID Column -->
<ng-container matColumnDef="userId">
<mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.id}} </mat-cell>
</ng-container>
<!-- Progress Column -->
<ng-container matColumnDef="progress">
<mat-header-cell *matHeaderCellDef mat-sort-header> Progress </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.progress}}% </mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="userName">
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
</ng-container>
<!-- Color Column -->
<ng-container matColumnDef="color">
<mat-header-cell *matHeaderCellDef mat-sort-header> Color </mat-header-cell>
<mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
<!-- Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license -->
таблица-сортировка-example.ts
import {Component, ViewChild} from '@angular/core';
import {DataSource} from '@angular/cdk/collections';
import {MatSort} from '@angular/material';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
/**
* @title Table with sorting
*/
@Component({
selector: 'table-sorting-example',
styleUrls: ['table-sorting-example.css'],
templateUrl: 'table-sorting-example.html',
})
export class TableSortingExample {
displayedColumns = ['userId', 'userName', 'progress', 'color'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort);
}
}
/** Constants used to fill up our data base. */
const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];
export interface UserData {
id: string;
name: string;
progress: string;
color: string;
}
/** An example database that the data source uses to retrieve data for the table. */
export class ExampleDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
get data(): UserData[] { return this.dataChange.value; }
constructor() {
// Fill up the database with 100 users.
for (let i = 0; i < 100; i++) { this.addUser(); }
}
/** Adds a new user to the database. */
addUser() {
const copiedData = this.data.slice();
copiedData.push(this.createNewUser());
this.dataChange.next(copiedData);
}
/** Builds and returns a new User. */
private createNewUser() {
const name =
NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' +
NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.';
return {
id: (this.data.length + 1).toString(),
name: name,
progress: Math.round(Math.random() * 100).toString(),
color: COLORS[Math.round(Math.random() * (COLORS.length - 1))]
};
}
}
/**
* Data source to provide what data should be rendered in the table. Note that the data source
* can retrieve its data in any way. In this case, the data source is provided a reference
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage
* the underlying data. Instead, it only needs to take the data and send the table exactly what
* should be rendered.
*/
export class ExampleDataSource extends DataSource<any> {
constructor(private _exampleDatabase: ExampleDatabase, private _sort: MatSort) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<UserData[]> {
const displayDataChanges = [
this._exampleDatabase.dataChange,
this._sort.sortChange,
];
return Observable.merge(...displayDataChanges).map(() => {
return this.getSortedData();
});
}
disconnect() {}
/** Returns a sorted copy of the database data. */
getSortedData(): UserData[] {
const data = this._exampleDatabase.data.slice();
if (!this._sort.active || this._sort.direction == '') { return data; }
return data.sort((a, b) => {
let propertyA: number|string = '';
let propertyB: number|string = '';
switch (this._sort.active) {
case 'userId': [propertyA, propertyB] = [a.id, b.id]; break;
case 'userName': [propertyA, propertyB] = [a.name, b.name]; break;
case 'progress': [propertyA, propertyB] = [a.progress, b.progress]; break;
case 'color': [propertyA, propertyB] = [a.color, b.color]; break;
}
let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
let valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1);
});
}
}
/** Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license */
Кто-нибудь знает, почему он отображается как онлайн-таблица, но не имеет функции сортировки?
angular
angular-material
Avern
источник
источник
ng test --sm=false
и посмотрите, что получится.Ответы:
Для всех, у кого может быть эта проблема: проблема заключалась в том, что я неправильно прочитал ссылку на API на веб-сайте angular материалов, в той части, в которой говорилось, что мне нужно импортировать MatSortModule. После того, как я изменил свой список импорта в app.module.ts на
это сработало нормально
источник
BrowserAnimationsModule
также импортируется в app.module.tsMatSortModule
иBrowserAnimationsModule
, и я убедился, что значение matColumnDef соответствует имени свойства, но я все еще не могу заставить его что-либо делать.У меня была проблема, что функция сортировки работала, но сортировка не выполнялась должным образом. Я понял, что
matColumnDef
у свойства my должно быть то же имя, наclass / interface
которое я ссылаюсьmatCellDef
.Согласно документации Angular Material :
Например:
name
ВmatColumnDef
директиве должно быть таким же , какname
используемая в<mat-cell>
компоненте.источник
element
, например эту `{{row.getName ()}}`Если таблица находится внутри * ngIf, она не будет работать. Он будет работать, если его изменить на [скрытый]
источник
<div *ngIf="xxx">
от<div [hidden]="!xxx">
Имя matColumnDef и имя фактического значения * matCellDef должны совпадать
Пример:
В моем случае oppNo совпадает с именем matColumnDef и именем * matCellDef, и сортировка работает нормально.
источник
У меня работает сортировка в блоке тайм-аута,
Если вы не хотите использовать крючки lifecykle.
источник
Я тоже столкнулся с этой проблемой. Поскольку вам нужно дождаться определения дочернего
AfterViewInit
элемента , вы должны реализовать и использовать , а не onInit.источник
ngAfterViewInit
? Остальное работало отngOnInit
. Просто чтобы попытаться понять, это исправлено благодаря вамЯ потратил часы на эту проблему. Прочитав несколько потоков, вот шаги, которые я сделал.
MatSortModule
.*ngIf
. Измените его ,[hidden]
как @zerg рекомендуется . (Я не понимаю почему)Надеюсь это поможет.
источник
Мое решение состояло в том, чтобы исправить несколько вещей (в основном объединить большинство решений на этой странице).
Что нужно проверить:
BrowserModule, MatTableModule, MatSortModule
Модули следует импортировать в файл корневых модулей.MatTableDatasource
класс и передайте в него массив данных в качестве параметра.*ngIf=....
директиву. Вместо этого используйте другие условные операции (все еще не понимаю, почему).источник
Для меня сработала замена * ngIf атрибутом [hidden] для тега mat-table. Как опубликовать это как ошибку в сообществе Angular Material?
источник
Я исправил это в своем сценарии, назвав данные таблицы с тем же именем, что и * matColumnDef. Например:
Вместо
источник
У меня было 2 проблемы.
Я получал данные из службы. Сортировка ngOnInit не работала. Заменено на
ngAfterViewInit () {this.dataSource.sort = this.sort; }
источник
Я нашел этот старый блог, который помог мне заставить его работать: https://www.jeffryhouser.com/index.cfm/2018/10/23/Five-Reasons-My-ngMaterial-Table-wont-sort
MatSortModule
matSort
заголовокMatTableDataSource
<table mat-table [dataSource]="this.products" matSort>
), но мне следовало использовать объект источника данных, который я инициализировал в коде (<table mat-table [dataSource]="this.dataSource" matSort>
). Источник данных инициализируется какdataSource = new MatTableDataSource(this.products)
ngOnInit
/ngAfterViewInit
MatTableDataSource
источник
Если ваша таблица находится внутри * ngIf и вы думаете, что это имеет какое-то отношение к тому, что она не сортирует вашу таблицу, то указание вашей собственной
sortingDataAccessor
функции может решить проблему, как это было со мной. У меня есть таблица внутри нескольких * ngIfs, и вынимать ее из этих * ngIfs не имело смысла:источник
Одна из причин, по которой MatSort может не работать, - это когда он добавляется в источник данных (т.е.
this.dataSource.sort = this.sort
) до того, как он определен. Для этого может быть несколько причин:если вы добавите сортировку в ngOnInit. На этом этапе шаблон еще не отрисован, поэтому MatSort, который вы получаете,
@ViewChild(MatSort, { static: true }) sort: MatSort;
не определен и, по понятным причинам, ничего не сделает. Решение этой проблемы - перейтиthis.dataSource.sort = sort
к ngAfterViewInit. Когда вызывается ngAfterViewInit, ваш компонент отображается, и должен быть определен MatSort.когда вы используете * ngIf, это ваш шаблон в элементе таблицы или один, если это родительские элементы, и этот * ngIf приводит к тому, что ваша таблица не отображается в момент, когда вы пытаетесь установить MatSort. Например, если у вас есть
*ngIf="dataSource.data.length > 0"
элемент таблицы (чтобы отображать его только при наличии данных), и вы устанавливаетеthis.dataSource.sort = this.sort
сразу после того, как вы установилиthis.dataSource.data
свои данные. Вид компонента еще не будет повторно отрисован, поэтому MatSort все равно будет неопределенным.Для того , чтобы получить MatSort на работу и по- прежнему условно показать таблицу вы можете решить , чтобы заменить
*ngIf
с ,[hidden]
как указано в нескольких других ответах. Однако, если вы хотите сохранить оператор * ngIf, вы можете использовать следующее решение. Это решение работает для Angular 9, я не тестировал его в предыдущих версиях, поэтому не уверен, работает ли оно там.Я нашел это решение здесь: https://github.com/angular/components/issues/10205
Вместо того, чтобы поставить:
используйте сеттер для matSort. Этот установщик сработает, как только matSort изменится в вашем представлении (т.е. определен в первый раз), он не сработает, когда вы измените свою сортировку, щелкнув стрелки. Это будет выглядеть так:
Если у вас есть другие функции, которые (программно) изменяют сортировку, я не уверен, сработает ли она снова, я не тестировал это. Если вы не хотите, чтобы сортировка устанавливалась только в том случае, если сортировка не определена, вы можете сделать что-то вроде этого:
источник
На самом деле имя matColumnDef (т.е. имя столбца) и имя вашего свойства класса / интерфейса должны быть одинаковыми, чтобы он работал.
Иногда мы не можем изменить имя нашего свойства класса / интерфейса, в этом случае мы можем реализовать настраиваемую сортировку, как показано ниже.
если мы выполним сортировку по столбцу id, это не сработает. Попробуйте использовать настраиваемую сортировку
источник
Для всех, кто не понимает, что эти наименования должны быть одинаковыми, я провел небольшое тестирование:
Это будет работать (имя свойства такое же, как у столбца def):
Это НЕ будет работать (имя свойства не совпадает с именем столбца def):
Fyi, это тоже НЕ работает (длина свойства):
И это тоже не так:
источник
Посмотрите, есть ли у вас ошибки javascript в консоли. Возможно, что-то еще не удалось выполнить до инициализации сортировки.
источник