state haben.TanStack Table verfügt über ein einfaches internes Zustandsverwaltungssystem, um den Zustand der Tabelle zu speichern und zu verwalten. Es ermöglicht Ihnen auch, jeden benötigten Zustand selektiv herauszuziehen, um ihn in Ihrer eigenen Zustandsverwaltung zu verwalten. Diese Anleitung führt Sie durch die verschiedenen Möglichkeiten, wie Sie mit dem Zustand der Tabelle interagieren und ihn verwalten können.
Sie müssen nichts Besonderes einrichten, damit der Tabellenstatus funktioniert. Wenn Sie nichts in die Optionen state, initialState oder einen der on[State]Change Tabellenoptionen übergeben, verwaltet die Tabelle ihren eigenen Zustand intern. Sie können auf jeden Teil dieses internen Zustands zugreifen, indem Sie die table.getState() API der Tabelleninstanz verwenden.
table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
//...
}))
someHandler() {
console.log(this.table.getState()) //access the entire internal state
console.log(this.table.getState().rowSelection) //access just the row selection state
}
table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
//...
}))
someHandler() {
console.log(this.table.getState()) //access the entire internal state
console.log(this.table.getState().rowSelection) //access just the row selection state
}
Wenn alles, was Sie für bestimmte Zustände tun müssen, darin besteht, ihre anfänglichen Standardwerte anzupassen, müssen Sie den Zustand immer noch nicht selbst verwalten. Sie können einfach Werte in der Option initialState der Tabelleninstanz festlegen.
table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
initialState: {
columnOrder: ['age', 'firstName', 'lastName'], //customize the initial column order
columnVisibility: {
id: false //hide the id column by default
},
expanded: true, //expand all rows by default
sorting: [
{
id: 'age',
desc: true //sort by age in descending order by default
}
]
},
//...
}))
table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
initialState: {
columnOrder: ['age', 'firstName', 'lastName'], //customize the initial column order
columnVisibility: {
id: false //hide the id column by default
},
expanded: true, //expand all rows by default
sorting: [
{
id: 'age',
desc: true //sort by age in descending order by default
}
]
},
//...
}))
Hinweis: Geben Sie jeden bestimmten Zustand nur entweder in initialState oder state an, aber nicht in beiden. Wenn Sie einen bestimmten Zustandswert sowohl an initialState als auch an state übergeben, überschreibt der initialisierte Zustand in state jeden entsprechenden Wert in initialState.
Wenn Sie einfachen Zugriff auf den Tabellenstatus in anderen Bereichen Ihrer Anwendung benötigen, macht es TanStack Table einfach, jeden oder den gesamten Tabellenstatus in Ihrem eigenen Zustandsverwaltungssystem zu steuern und zu verwalten. Dies können Sie tun, indem Sie Ihren eigenen Zustand und Ihre eigenen Zustandsverwaltungsfunktionen an die Tabellenoptionen state und on[State]Change übergeben.
Sie können nur den Zustand steuern, auf den Sie einfachen Zugriff benötigen. Sie müssen NICHT den gesamten Tabellenstatus steuern, wenn Sie dies nicht tun müssen. Es wird empfohlen, nur den Zustand zu steuern, den Sie von Fall zu Fall benötigen.
Um einen bestimmten Zustand zu steuern, müssen Sie sowohl den entsprechenden state-Wert als auch die Funktion on[State]Change an die Tabelleninstanz übergeben.
Nehmen wir Filterung, Sortierung und Paginierung als Beispiel in einem "manuellen" serverseitigen Datenabrufszenario. Sie können den Filter-, Sortier- und Paginierungsstatus in Ihrer eigenen Zustandsverwaltung speichern, aber andere Zustände wie Spaltenreihenfolge, Spalten-Sichtbarkeit usw. weglassen, wenn Ihre API diese Werte nicht benötigt.
import {signal} from '@angular/core';
import {SortingState, ColumnFiltersState, PaginationState} from '@tanstack/angular-table'
import {toObservable} from "@angular/core/rxjs-interop";
import {combineLatest, switchMap} from 'rxjs';
class TableComponent {
readonly columnFilters = signal<ColumnFiltersState>([]) //no default filters
readonly sorting = signal<SortingState>([
{
id: 'age',
desc: true, //sort by age in descending order by default
}
])
readonly pagination = signal<PaginationState>({
pageIndex: 0,
pageSize: 15
})
//Use our controlled state values to fetch data
readonly data$ = combineLatest({
filters: toObservable(this.columnFilters),
sorting: toObservable(this.sorting),
pagination: toObservable(this.pagination)
}).pipe(
switchMap(({filters, sorting, pagination}) => fetchData(filters, sorting, pagination))
)
readonly data = toSignal(this.data$);
readonly table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
//...
state: {
columnFilters: this.columnFilters(), //pass controlled state back to the table (overrides internal state)
sorting: this.sorting(),
pagination: this.pagination(),
},
onColumnFiltersChange: updater => { //hoist columnFilters state into our own state management
updater instanceof Function
? this.columnFilters.update(updater)
: this.columnFilters.set(updater)
},
onSortingChange: updater => {
updater instanceof Function
? this.sorting.update(updater)
: this.sorting.set(updater)
},
onPaginationChange: updater => {
updater instanceof Function
? this.pagination.update(updater)
: this.pagination.set(updater)
},
}))
}
//...
import {signal} from '@angular/core';
import {SortingState, ColumnFiltersState, PaginationState} from '@tanstack/angular-table'
import {toObservable} from "@angular/core/rxjs-interop";
import {combineLatest, switchMap} from 'rxjs';
class TableComponent {
readonly columnFilters = signal<ColumnFiltersState>([]) //no default filters
readonly sorting = signal<SortingState>([
{
id: 'age',
desc: true, //sort by age in descending order by default
}
])
readonly pagination = signal<PaginationState>({
pageIndex: 0,
pageSize: 15
})
//Use our controlled state values to fetch data
readonly data$ = combineLatest({
filters: toObservable(this.columnFilters),
sorting: toObservable(this.sorting),
pagination: toObservable(this.pagination)
}).pipe(
switchMap(({filters, sorting, pagination}) => fetchData(filters, sorting, pagination))
)
readonly data = toSignal(this.data$);
readonly table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
//...
state: {
columnFilters: this.columnFilters(), //pass controlled state back to the table (overrides internal state)
sorting: this.sorting(),
pagination: this.pagination(),
},
onColumnFiltersChange: updater => { //hoist columnFilters state into our own state management
updater instanceof Function
? this.columnFilters.update(updater)
: this.columnFilters.set(updater)
},
onSortingChange: updater => {
updater instanceof Function
? this.sorting.update(updater)
: this.sorting.set(updater)
},
onPaginationChange: updater => {
updater instanceof Function
? this.pagination.update(updater)
: this.pagination.set(updater)
},
}))
}
//...
Alternativ können Sie den gesamten Tabellenstatus mit der Tabellenoption onStateChange steuern. Dies wird den gesamten Tabellenstatus in Ihr eigenes Zustandsverwaltungssystem "hoisten". Seien Sie bei diesem Ansatz vorsichtig, da die Übertragung einiger sich häufig ändernder Zustände nach oben in einer Komponentenstruktur, wie z. B. der columnSizingInfo-Status, zu Leistungsproblemen führen kann.
Ein paar weitere Tricks könnten notwendig sein, damit dies funktioniert. Wenn Sie die Tabellenoption onStateChange verwenden, müssen die Anfangswerte von state mit allen relevanten Zustandswerten für alle Funktionen, die Sie verwenden möchten, gefüllt werden. Sie können entweder alle anfänglichen Zustandswerte manuell aufschreiben oder einen Konstruktor auf besondere Weise verwenden, wie unten gezeigt.
class TableComponent {
// create an empty table state, we'll override it later
readonly state = signal({} as TableState);
// create a table instance with default state values
readonly table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
// our fully controlled state overrides the internal state
state: this.state(),
onStateChange: updater => {
// any state changes will be pushed up to our own state management
this.state.set(
updater instanceof Function ? updater(this.state()) : updater
)
}
}))
constructor() {
// set the initial table state
this.state.set({
// populate the initial state with all of the default state values
// from the table instance
...this.table.initialState,
pagination: {
pageIndex: 0,
pageSize: 15, // optionally customize the initial pagination state.
},
})
}
}
class TableComponent {
// create an empty table state, we'll override it later
readonly state = signal({} as TableState);
// create a table instance with default state values
readonly table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
// our fully controlled state overrides the internal state
state: this.state(),
onStateChange: updater => {
// any state changes will be pushed up to our own state management
this.state.set(
updater instanceof Function ? updater(this.state()) : updater
)
}
}))
constructor() {
// set the initial table state
this.state.set({
// populate the initial state with all of the default state values
// from the table instance
...this.table.initialState,
pagination: {
pageIndex: 0,
pageSize: 15, // optionally customize the initial pagination state.
},
})
}
}
Bisher haben wir gesehen, wie die Tabellenoptionen on[State]Change und onStateChange die Tabellenstatusänderungen in unsere eigene Zustandsverwaltung "hoisten". Es gibt jedoch ein paar Dinge, die Sie bei der Verwendung dieser Optionen beachten sollten.
Die Angabe eines on[State]Change-Callbacks teilt der Tabelleninstanz mit, dass dies ein gesteuerter Zustand sein wird. Wenn Sie den entsprechenden state-Wert nicht angeben, wird dieser Zustand mit seinem Anfangswert "eingefroren".
class TableComponent {
sorting = signal<SortingState>([])
table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
//...
state: {
sorting: this.sorting(), // required because we are using `onSortingChange`
},
onSortingChange: updater => { // makes the `state.sorting` controlled
updater instanceof Function
? this.sorting.update(updater)
: this.sorting.set(updater)
}
}))
}
class TableComponent {
sorting = signal<SortingState>([])
table = createAngularTable(() => ({
columns: this.columns,
data: this.data(),
//...
state: {
sorting: this.sorting(), // required because we are using `onSortingChange`
},
onSortingChange: updater => { // makes the `state.sorting` controlled
updater instanceof Function
? this.sorting.update(updater)
: this.sorting.set(updater)
}
}))
}
Die Callbacks on[State]Change und onStateChange funktionieren genau wie die setState-Funktionen in React. Die Updater-Werte können entweder ein neuer Zustandswert oder eine Callback-Funktion sein, die den vorherigen Zustandswert übernimmt und den neuen Zustandswert zurückgibt.
Welche Auswirkungen hat das? Das bedeutet, dass Sie, wenn Sie zusätzliche Logik in einem der on[State]Change-Callbacks hinzufügen möchten, dies tun können, aber Sie müssen prüfen, ob der neue eingehende Updater-Wert eine Funktion oder ein Wert ist.
Deshalb werden Sie in den obigen Beispielen das Muster updater instanceof Function ? this.state.update(updater) : this.state.set(updater) sehen. Dieses Muster prüft, ob der Updater eine Funktion ist, und wenn ja, ruft es die Funktion mit dem vorherigen Zustandswert auf, um den neuen Zustandswert zu erhalten, oder das Signal erfordert, dass signal.update mit dem Updater aufgerufen wird, anstatt signal.set.
Alle komplexen Zustände in TanStack Table haben ihre eigenen TypeScript-Typen, die Sie importieren und verwenden können. Dies kann hilfreich sein, um sicherzustellen, dass Sie die richtigen Datenstrukturen und Eigenschaften für die von Ihnen gesteuerten Zustandswerte verwenden.
import {createAngularTable, type SortingState} from '@tanstack/angular-table'
class TableComponent {
readonly sorting = signal<SortingState>([
{
id: 'age', // you should get autocomplete for the `id` and `desc` properties
desc: true,
}
])
}
import {createAngularTable, type SortingState} from '@tanstack/angular-table'
class TableComponent {
readonly sorting = signal<SortingState>([
{
id: 'age', // you should get autocomplete for the `id` and `desc` properties
desc: true,
}
])
}
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.