APIやDBでは1、2、9のようなコード値を持ち、画面では「有効」「停止」「削除済み」のようなラベルで見せたいことがあります。
DataTablesではcolumns.renderを使うと、データとして持つ値と画面に出す値を分けられます。
公式ページ
やりたいこと
たとえば、以下のようなデータがあるとします。
const users = [
{ id: 1, name: '山田 太郎', status: '1' },
{ id: 2, name: '佐藤 花子', status: '2' },
{ id: 3, name: '鈴木 一郎', status: '9' }
];
statusには物理値として1、2、9が入っています。
このままDataTablesに表示すると、画面にも1、2、9が表示されます。
new DataTable('#usersTable', {
data: users,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'name', title: '名前' },
{ data: 'status', title: 'ステータス' }
]
});
ユーザーに見せたいのは物理値ではなく、次のような表示用の値です。
| 物理値 | 表示用の論理値 |
| — | — |
| 1 | 有効 |
| 2 | 停止 |
| 9 | 削除済み |
columns.renderで表示値を変換する
DataTablesでは、列定義のrenderで表示内容を加工できます。
const STATUS_LABELS = {
'1': '有効',
'2': '停止',
'9': '削除済み'
};
new DataTable('#usersTable', {
data: users,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'name', title: '名前' },
{
data: 'status',
title: 'ステータス',
render: function (data) {
return STATUS_LABELS[data] ?? '不明';
}
}
]
});
これで、元データのstatusは1、2、9のまま、画面には「有効」「停止」「削除済み」と表示できます。
typeを見て表示、検索、ソートを分ける
render関数には、DataTablesからdata、type、rowなどが渡されます。
render: function (data, type, row) {
// data: columns.dataで指定した値
// type: display / filter / sort / type など
// row: 行全体のデータ
}
重要なのはtypeです。
DataTablesは、表示、検索、ソートなどの用途ごとにrenderを呼び出します。
たとえば、表示と検索では「有効」を使い、ソートでは元の物理値を使いたい場合は、次のように書けます。
const STATUS_LABELS = {
'1': '有効',
'2': '停止',
'9': '削除済み'
};
new DataTable('#usersTable', {
data: users,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'name', title: '名前' },
{
data: 'status',
title: 'ステータス',
render: function (data, type) {
if (type === 'display' || type === 'filter') {
return STATUS_LABELS[data] ?? '不明';
}
return data;
}
}
]
});
この書き方にすると、画面表示と検索にはラベルを使い、ソートや型判定には元の物理値を使えます。
表示順を制御したい場合
物理値の大小と、画面上の並び順が一致しない場合もあります。
たとえば、以下の順番で並べたいとします。
- 有効
- 停止
- 削除済み
その場合は、表示用ラベルとは別にソート用の値を用意します。
const STATUS_LABELS = {
'1': '有効',
'2': '停止',
'9': '削除済み'
};
const STATUS_SORT_ORDER = {
'1': 1,
'2': 2,
'9': 3
};
new DataTable('#usersTable', {
data: users,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'name', title: '名前' },
{
data: 'status',
title: 'ステータス',
render: function (data, type) {
if (type === 'display' || type === 'filter') {
return STATUS_LABELS[data] ?? '不明';
}
if (type === 'sort' || type === 'type') {
return STATUS_SORT_ORDER[data] ?? 999;
}
return data;
}
}
]
});
これで、表示は「有効」「停止」「削除済み」のまま、ソートはSTATUS_SORT_ORDERの値で制御できます。
rowを使って複数項目から表示値を作る
renderでは、行全体のデータをrowから参照できます。
たとえば、statusとisLockedを組み合わせて表示を変えたい場合です。
const users = [
{ id: 1, name: '山田 太郎', status: '1', isLocked: false },
{ id: 2, name: '佐藤 花子', status: '1', isLocked: true },
{ id: 3, name: '鈴木 一郎', status: '2', isLocked: false }
];
const STATUS_LABELS = {
'1': '有効',
'2': '停止',
'9': '削除済み'
};
new DataTable('#usersTable', {
data: users,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'name', title: '名前' },
{
data: 'status',
title: 'ステータス',
render: function (data, type, row) {
if (type !== 'display' && type !== 'filter') {
return data;
}
const label = STATUS_LABELS[data] ?? '不明';
return row.isLocked ? `${label}(ロック中)` : label;
}
}
]
});
dataだけで足りない場合は、rowを使って行全体から表示値を組み立てると便利です。
共通関数にして使い回す
ステータス変換を複数のDataTablesで使う場合は、変換処理を共通関数にしておくと楽です。
const STATUS_LABELS = {
'1': '有効',
'2': '停止',
'9': '削除済み'
};
const STATUS_SORT_ORDER = {
'1': 1,
'2': 2,
'9': 3
};
function renderStatus(data, type) {
if (type === 'display' || type === 'filter') {
return STATUS_LABELS[data] ?? '不明';
}
if (type === 'sort' || type === 'type') {
return STATUS_SORT_ORDER[data] ?? 999;
}
return data;
}
new DataTable('#usersTable', {
data: users,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'name', title: '名前' },
{
data: 'status',
title: 'ステータス',
render: renderStatus
}
]
});
この形にしておくと、別の一覧でもrender: renderStatusと書くだけで同じ変換を使えます。
HTMLを返す場合の注意
renderではHTML文字列を返すこともできます。
function renderStatus(data, type) {
const label = STATUS_LABELS[data] ?? '不明';
if (type === 'display') {
return `<span class="status-label status-${data}">${label}</span>`;
}
if (type === 'filter') {
return label;
}
return data;
}
ただし、外部入力をそのままHTMLとして返すとXSSの原因になります。
表示用HTMLを返す場合は、コード値のように安全な値だけを使う、または文字列をエスケープしてから表示するようにしてください。
まとめ
物理値を表示用ラベルに変換するなら、columns.renderに変換処理をまとめます。
基本は、物理値と表示ラベルの対応表を作り、renderで変換するだけです。
検索やソートも考慮する場合は、typeを見て返す値を分けます。
display: 画面に表示する値filter: 検索に使う値sort: ソートに使う値type: 型判定に使う値
物理値はデータとして保持し、画面にはユーザーに分かりやすい論理値を表示する、という分け方にすると、DataTablesの一覧を扱いやすくできます。
コメント