ツリーテーブル

TreeTable は、階層データを表形式で表示するために使用されます。


import TreeTable from 'primevue/treetable';
import Column from 'primevue/column';

TreeTable は、として TreeNode インスタンスのコレクションと、表現のために子として Column コンポーネントが必要です。ノードを切り替える要素を持つ列は、expander を有効にする必要があります。


<TreeTable :value="nodes" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

カラムはプログラムで作成できます。


<TreeTable :value="nodes" tableStyle="min-width: 50rem">
    <Column v-for="col of columns" :key="col.field" :field="col.field" :header="col.header" :expander="col.expander"></Column>
</TreeTable>

展開状態は expandedKeys プロパティで制御されます。 expandedKeys は、キーがノードキーを参照し、値が展開状態を表すオブジェクトである必要があります。例:{'0-0': true}


<Button @click="toggleApplications" label="Toggle Applications" />
<TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" class="mt-6" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

header および footer スロットのカスタムコンテンツは、テンプレートを使用してサポートされます。


<TreeTable :value="nodes" tableStyle="min-width: 50rem">
    <template #header>
        <div class="text-xl font-bold">File Viewer</div>
    </template>
    <Column field="name" header="Name" expander style="width: 250px"></Column>
    <Column field="size" header="Size" style="width: 150px"></Column>
    <Column field="type" header="Type" style="width: 150px"></Column>
    <Column style="width: 10rem">
        <template #body>
            <div class="flex flex-wrap gap-2">
                <Button type="button" icon="pi pi-search" rounded />
                <Button type="button" icon="pi pi-pencil" rounded severity="success" />
            </div>
        </template>
    </Column>
    <template #footer>
        <div class="flex justify-start">
            <Button icon="pi pi-refresh" label="Reload" severity="warn" />
        </div>
    </template>
</TreeTable>

通常のテーブルに加えて、代替サイズを持つ代替テーブルも利用可能です。


<TreeTable :value="nodes" :size="size.value" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

ページネーションは、paginator プロパティを追加し、ページあたりの rows を定義することで有効になります。


<TreeTable :value="nodes" :paginator="true" :rows="5" :rowsPerPageOptions="[5, 10, 25]" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

ページネーターUIは、paginatorTemplateプロパティを使用してカスタマイズされます。各要素は、独自のUIでさらにカスタマイズしてデフォルトのUIを置き換えることもできます。詳細なカスタマイズオプションについては、ページネーターコンポーネントを参照してください。


<TreeTable
    :value="nodes"
    :paginator="true"
    :rows="5"
    :rowsPerPageOptions="[5, 10, 25, 50]"
    paginatorTemplate="RowsPerPageDropdown FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"
    currentPageReportTemplate="{first} to {last} of {totalRecords}"
    tableStyle="min-width: 50rem"
>
    <template #paginatorstart>
        <Button type="button" icon="pi pi-refresh" text />
    </template>
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
    <template #paginatorend>
        <Button type="button" icon="pi pi-download" text />
    </template>
</TreeTable>

カラムのソートは、sortable プロパティを追加することで有効になります。


<TreeTable :value="nodes" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
    <Column field="size" header="Size" sortable style="width: 33%"></Column>
    <Column field="type" header="Type" sortable style="width: 33%"></Column>
</TreeTable>

sortModemultiple として定義することで、複数のカラムをソートできます。このモードでは、ヘッダーをクリックするときに metaKey(例:)を押す必要があります。


<TreeTable :value="nodes" sortMode="multiple" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
    <Column field="size" header="Size" sortable style="width: 33%"></Column>
    <Column field="type" header="Type" sortable style="width: 33%"></Column>
</TreeTable>

removableSort が存在する場合、3回目のクリックでカラムからソートが削除されます。


<TreeTable :value="nodes" sortMode="multiple" removableSort tableStyle="min-width: 50rem">
    <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
    <Column field="size" header="Size" sortable style="width: 33%"></Column>
    <Column field="type" header="Type" sortable style="width: 33%"></Column>
</TreeTable>

フィルタリングは、Column に filter プロパティを追加することで有効になります。filterMode はフィルタリング戦略を指定します。lenient モードでは、クエリがノードと一致する場合、ノードの子孫はすべて含まれるため、ノードの子はそれ以上検索されません。一方、strict モードでは、クエリがノードと一致する場合、すべての子孫でフィルタリングが続行されます。フィルタリングをサポートするすべてのカラムを検索するために、globalFilter と呼ばれる一般的なフィルターも提供されます。


<SelectButton v-model="filterMode" optionLabel="label" dataKey="label" :options="filterOptions" />
<TreeTable :value="nodes" :filters="filters" :filterMode="filterMode.value">
    <template #header>
        <div class="flex justify-end">
            <IconField>
                <InputIcon class="pi pi-search" />
                <InputText v-model="filters['global']" placeholder="Global Search" />
            </IconField>
        </div>
    </template>
    <Column field="name" header="Name" expander style="min-width: 12rem">
        <template #filter>
            <InputText v-model="filters['name']" type="text" placeholder="Filter by name" />
        </template>
    </Column>
    <Column field="size" header="Size" style="min-width: 12rem">
        <template #filter>
            <InputText v-model="filters['size']" type="text" placeholder="Filter by size" />
        </template>
    </Column>
    <Column field="type" header="Type" style="min-width: 12rem">
        <template #filter>
            <InputText v-model="filters['type']" type="text" placeholder="Filter by type" />
        </template>
    </Column>
</TreeTable>

単一ノード選択は、selectionModesingle として設定し、選択値バインディングを管理するために selectionKeys プロパティを設定することで構成されます。

デフォルトでは、ノードの選択を解除するには metaKey(例:)を押す必要がありますが、これは metaKeySelection プロパティを無効にすることで設定できます。タッチ対応デバイスでは、このオプションは効果がなく、false に設定した場合と同じ動作になります。


<ToggleSwitch v-model="metaKey" inputId="input-metakey" />

<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="single" :metaKeySelection="metaKey" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

selectionModemultiple に設定することで、複数のノードを選択できます。デフォルトの複数選択モードでは、既存の選択に追加するために metaKey(例:)を押す必要はありません。オプションの metaKeySelection が存在する場合、新しいノードを選択するには meta キーを押す必要があるように動作が変更されます。タッチ対応デバイスでは、TreeTable は常に metaKey を無視することに注意してください。

複数選択モードでは、値バインディングは、キーがノードキーで、値が選択を示すブール値であるキーと値のペアである必要があります。


<ToggleSwitch v-model="metaKey" inputId="input-metakey" />

<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="multiple" :metaKeySelection="metaKey" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

チェックボックスによる複数ノードの選択は、selectionModecheckbox として構成することで有効になります。

チェックボックス選択モードでは、値バインディングは、キー(または dataKey)がノードキーであり、値がノードのチェック状態を表す checked および partialChecked プロパティを持つオブジェクトであるキーと値のペアである必要があります。


{
    '0-0': {
        partialChecked: false,
        checked: true
    }
}


<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="checkbox" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

TreeTable は、選択イベントをリッスンするために nodeSelect および nodeUnselect イベントを提供します。


<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="single" @nodeSelect="onNodeSelect" @nodeUnselect="onNodeUnselect" :metaKeySelection="false" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

遅延モードは、大きなデータセットを処理するのに便利です。データ全体をロードする代わりに、ページングソート、および フィルタリング が発生するたびに、対応するコールバックを呼び出すことによって、小さなデータチャンクがロードされます。以下のサンプルは、メモリ内リストとタイムアウトを使用してリモートデータソースからデータを遅延ロードすることを模倣し、ネットワーク接続を模倣しています。

lazy プロパティを有効にし、論理行数を射影クエリを実行して totalRecords に割り当てることが実装の重要な要素です。これにより、ページネーターは、実際にはページ上に存在しない totalRecords サイズのレコードが実際に存在すると想定して UI を表示します。現在のページに表示されているレコードのみが存在します。

さらに、ルート要素のみをロードする必要があり、子は nodeExpand コールバックを使用してオンデマンドでロードできます。


<TreeTable :value="nodes" :lazy="true" :paginator="true" :rows="rows" :loading="loading"
    @nodeExpand="onExpand" @page="onPage" :totalRecords="totalRecords" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander></Column>
    <Column field="size" header="Size"></Column>
    <Column field="type" header="Type"></Column>
</TreeTable>

データビューポートに scrollHeight とともに scrollable プロパティを追加すると、固定ヘッダーで垂直スクロールが可能になります。


<TreeTable :value="nodes" scrollable scrollHeight="270px" tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander style="width: 34%"></Column>
    <Column field="size" header="Size" style="width: 33%"></Column>
    <Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>

フレックススクロール機能により、スクロール可能なビューポートセクションは固定値ではなく動的になり、テーブルの親サイズに対して相対的に拡大または縮小できます。下のボタンをクリックして、データビューポートがサイズ変更に応じて自動的に調整される、最大化可能なダイアログを表示します。


<Button label="Show" icon="pi pi-external-link" @click="dialogVisible = true" />
<Dialog v-model:visible="dialogVisible" header="Flex Scroll" :style="{ width: '75vw' }" maximizable modal :contentStyle="{ height: '300px' }">
    <TreeTable :value="nodes" :scrollable="true" scrollHeight="flex" tableStyle="min-width: 50rem">
        <Column field="name" header="Name" :expander="true" style="min-width: 200px"></Column>
        <Column field="size" header="Size" style="min-width: 200px"></Column>
        <Column field="type" header="Type" style="min-width: 200px"></Column>
    </TreeTable>
    <template #footer>
        <Button label="Ok" icon="pi pi-check" @click="dialogVisible = false" />
    </template>
</Dialog>

テーブルの幅が親の幅を超えると、水平スクロールバーが表示されます。


<TreeTable :value="nodes" scrollable scrollHeight="300px">
    <Column field="name" header="Name" expander style="min-width: 250px"></Column>
    <Column field="size" header="Size" style="min-width: 200px"></Column>
    <Column field="type" header="Type 2" style="min-width: 200px"></Column>
    <Column field="size" header="Size 2" style="min-width: 200px"></Column>
    <Column field="type" header="Type 3" style="min-width: 200px"></Column>
    <Column field="size" header="Size 3" style="min-width: 200px"></Column>
</TreeTable>

カラムで frozen プロパティを有効にすることで、水平スクロール中にカラムを固定できます。位置は、left または right に設定できる alignFrozen で定義されます。


<TreeTable :value="nodes" scrollable scrollHeight="300px">
    <Column field="name" header="Name" expander frozen style="min-width: 250px" class="font-bold"></Column>
    <Column field="size" header="Size" style="min-width: 200px"></Column>
    <Column field="type" header="Type 2" style="min-width: 200px"></Column>
    <Column field="size" header="Size 2" style="min-width: 200px"></Column>
    <Column field="type" header="Type 3" style="min-width: 200px"></Column>
    <Column field="size" header="Size 3" style="min-width: 200px"></Column>
</TreeTable>

resizableColumns が有効になっている場合、カラムはドラッグアンドドロップでサイズ変更できます。デフォルトのサイズ変更モードは fit で、テーブル全体の幅は変更されません。


<TreeTable :value="nodes" :resizableColumns="true" showGridlines tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander></Column>
    <Column field="size" header="Size"></Column>
    <Column field="type" header="Type"></Column>
</TreeTable>

columnResizeModeexpand として設定すると、テーブルの幅も変更されます。


<TreeTable :value="nodes" :resizableColumns="true" columnResizeMode="expand" showGridlines tableStyle="min-width: 50rem">
    <Column field="name" header="Name" expander></Column>
    <Column field="size" header="Size"></Column>
    <Column field="type" header="Type"></Column>
</TreeTable>

条件に基づくカラムの表示/非表示は、動的カラムで実装できます。このサンプルでは、MultiSelect を使用して表示されるカラムを管理しています。


<TreeTable :value="nodes" tableStyle="min-width: 50rem">
    <template #header>
        <div style="text-align:left">
            <MultiSelect :modelValue="selectedColumns" @update:modelValue="onToggle" :options="columns" optionLabel="header" class="w-full sm:w-64" display="chip"/>
        </div>
    </template>
    <Column field="name" header="Name" :expander="true"></Column>
    <Column v-for="col of selectedColumns" :field="col.field" :header="col.header" :key="col.field"></Column>
</TreeTable>

スクリーンリーダー

DataTable は、tableProps オプションで属性を拡張できる treegrid 要素を使用します。このプロパティにより、aria-labelaria-describedby などの aria ロールと属性を渡して、リーダーのテーブルを定義できます。テーブルのデフォルトロールは table です。ヘッダー、本文、フッター要素は rowgroup を使用し、行は row ロールを使用し、ヘッダーセルは columnheader を持ち、本文セルは cell ロールを使用します。ソート可能なヘッダーは、"ascending" または "descending" に設定された aria-sort 属性を利用します。

行要素は、状態の aria-expanded と、階層を定義する aria-posinsetaria-setsize、および aria-level 属性を管理します。

選択が有効になっている場合、aria-selected は行で true に設定されます。チェックボックスモードでは、TreeTableコンポーネントは非表示のネイティブチェックボックス要素を使用します。

編集可能なセルはカスタムテンプレートを使用しているため、必要に応じてARIAロールと属性を手動で管理する必要があります。

ページネータはDataTable内で使用されるスタンドアロンコンポーネントです。アクセシビリティ機能の詳細については、ページネータを参照してください。

ソート可能なヘッダーのキーボードサポート

キー機能
Tabヘッダー間を移動します。
Enter列をソートします。
Space列をソートします。

キーボードサポート

キー機能
Tabコンポーネントにフォーカスが当たったときに、選択されている最初のノードにフォーカスを移動します。何も選択されていない場合は、最初の要素にフォーカスが当たります。フォーカスが既にコンポーネント内にある場合は、ページのタブシーケンスの次のフォーカス可能な要素にフォーカスを移動します。
Shift + Tabコンポーネントにフォーカスが当たったときに、選択されている最後のノードにフォーカスを移動します。何も選択されていない場合は、最初の要素にフォーカスが当たります。フォーカスが既にコンポーネント内にある場合は、ページのタブシーケンスの前のフォーカス可能な要素にフォーカスを移動します。
Enterフォーカスされているツリーノードを選択します。
Spaceフォーカスされているツリーノードを選択します。
下矢印次のツリーノードにフォーカスを移動します。
上矢印前のツリーノードにフォーカスを移動します。
右矢印ノードが閉じている場合はノードを開き、そうでない場合は最初の子ノードにフォーカスを移動します。
左矢印ノードが開いている場合はノードを閉じ、そうでない場合は親ノードにフォーカスを移動します。
Home同じレベルの最初のノードにフォーカスを移動します。
End同じレベルの最後のノードにフォーカスを移動します。