データテーブル
リストのシグナルの行を、型の付いた列の下に並べる表です。並べ替え、絞り込み、ページ送り、行の選択をブラウザで行うほか、1 ページずつサーバーに求めることもできます。
実行結果
use hypersig::{NumberFormat, Page, Signals};
use hypersig_ui::{Column, DataTable, TableState, TableText};
use serde::{Deserialize, Serialize};
#[derive(Signals, Serialize, Deserialize)]
pub struct Payment {
id: i32,
email: String,
amount: f64,
}
#[derive(Signals, Serialize, Deserialize)]
pub struct Ledger {
payments: Vec<Payment>,
chosen: Vec<i32>,
table: TableState,
}
pub fn page() -> Page<Ledger> {
let payments = [
("ken99@example.com", 316.0),
("abe45@example.com", 242.0),
("monserrat44@example.com", 837.0),
("silas22@example.com", 874.0),
("carmella@example.com", 721.0),
("jason78@example.com", 450.0),
("sarah23@example.com", 120.5),
]
.into_iter()
.zip(1..)
.map(|((email, amount), id)| Payment {
id,
email: email.to_owned(),
amount,
})
.collect();
let table = DataTable::new(
"支払い",
Ledger::table(),
Ledger::payments(),
|payment| payment.at(Payment::id()),
)
.selectable(Ledger::chosen(), |payment| payment.at(Payment::id()))
.filter(
"メールアドレスで絞り込む",
|payment| payment.at(Payment::email()),
)
.paginate(5)
.text(TableText {
empty: "該当する行はありません。"
.to_owned(),
select_row: "行を選ぶ"
.to_owned(),
select_all: "すべての行を選ぶ"
.to_owned(),
previous_page: "前のページ"
.to_owned(),
next_page: "次のページ"
.to_owned(),
expand_row: "行の詳細を表示"
.to_owned(),
})
.sortable_column(
Column::text(
"メールアドレス",
Payment::email(),
),
|payment| payment.at(Payment::email()),
)
.sortable_column(
Column::formatted(
"金額",
Payment::amount(),
NumberFormat::new().digits(2).prefix("$"),
),
|payment| payment.at(Payment::amount()),
);
Page::new(
"支払い",
Ledger {
payments,
chosen: Vec::new(),
table: TableState::default(),
},
)
.child(table)
}アクセシビリティ
見出しに scope="col" を付けた <table> です。並べ替えられる列の見出しはボタンを持ち、その列で昇順か降順に並んでいるか、並んでいないかを aria-sort で伝えます。見出しのチェックボックスは role="checkbox" のボタンで、一部の行が選ばれている間は aria-checked が mixed になります。ネイティブのチェックボックスの中間状態はプロパティで、属性からは設定できないためです。
列は行の型のフィールドから作るので、別の構造体のフィールドを渡すとコンパイルエラーになります。sortable_column で並べ替えるキーは数値か文字列に限られます。表は絞り込みの文字列、ページ、並べ替えた列を、ページのシグナルにある TableState のフィールドに持ちます。並べ替えはリストのシグナルそのものの順序を変えます。選択は、選んだ行のキーのリストとしてページの別のシグナルに持つので、行の型に選択用のフィールドは要りません。ServerTable ではページを移っても選択が残ります。
ブラウザは変更のたびに行を数え直し、絞り込みとページ送りを両方使うと、その手間は行数の 2 乗で増えます。数千行のリストには ServerTable を使ってください。絞り込みの欄、並べ替えの見出し、ページのボタンが TableState を書き換えてから、それを引数にアクションを呼びます。アクションは、そのページの行と総数をパッチで返します。並べ替えられる列は #[derive(Segment)] を付けた列挙型をキーに取り、サーバーは TableState::sorting で状態からキーを読み戻します。このサイトにはサーバーがないので下のデモはブラウザだけで動き、examples/ui には DataTable と並べて ServerTable を置いています。
ServerTable の状態を URL に残すには、Option のフィールドを持ち #[derive(Search)] を付けたアプリケーション自身の構造体を、ページのルートのクエリパラメータにします。こうするとクエリ文字列のないアドレスも読み込めます。ページのハンドラはそこから TableState::with_sorting で TableState を作り、アクションは状態が指す URL を Patches::replace_url で答えに付けます。再読み込みしても、共有したリンクを開いても、同じページの行が出ます。TableState そのものをクエリパラメータにしないのは、フィールドが 1 つでも欠けた URL に 400 が返るためです。
| キー | 動作 |
|---|---|
| Space | フォーカスのあるチェックボックスを切り替えます。見出しのチェックボックスでは、すべての行を選び、すべて選ばれていれば選択を外します。 |
| Enter、Space | 列の見出しで押すと、その列で行を並べ替えます。行の先頭のボタンで押すと、その行の詳細を開閉します。 |
API
| 項目 | 概要 |
|---|---|
DataTable::new | label を名前に持ち、rows を key で並べ、状態を state に持つ空の表 |
column | それまでに足した列の後ろに column を足します。 |
sortable_column | 見出しで行を key の順に並べ替える列 column を、それまでに足した列の後ろに足します。 |
selectable | 選んだ行の key を selected に持つチェックボックスの列を先頭に足します。 |
expandable | 行の下に details を開閉するボタンの列を先頭に足し、開いている行の key を expanded に持ちます。 |
filter | label を名前に持つ欄を足し、text がその欄の文字列を含む行だけを表示します。 |
paginate | 一度に size 行を表示し、前と次のページに移るボタンを置きます。 |
max_height | 表の高さを height までに抑え、見出しを止めたまま行をスクロールさせます。 |
Column::text | 見出しが header で、各行の文字列のフィールド field を表示する列 |
Column::number | 見出しが header で、数値のフィールド field を行末に揃えて表示する列 |
Column::formatted | 見出しが header で、数値のフィールド field を format の形で表示する列 |
Column::custom | 見出しが header で、各行に対して render が返す要素をセルに入れる列 |
visible | when が真の間だけ列を表示します。 |
TableState | DataTable と ServerTable が持つシグナル。絞り込みの文字列、ページ、並べ替え |
TableText | DataTable と ServerTable が表示する言葉と、操作部品に付ける名前 |
ServerTable::new | label を名前に持ち、rows を key で並べ、行を取りに load を実行する空の表 |
ServerTable::sortable_column | 見出しでサーバーに key での並べ替えを求める列 column を、それまでに足した列の後ろに足します。 |
ServerTable::selectable | 選んだ行の key を selected に持つチェックボックスの列を先頭に足します。 |
ServerTable::filter | label を名前に持つ欄を足し、サーバーがその文字列で行を絞り込みます。 |
ServerTable::paginate | total 行のうち size 行ずつのページを表示し、前と次のページに移るボタンを置きます。 |
TableState::sorting | ServerTable が並べ替えている列のキーと、その向き |