樹狀表格

樹狀表格用於以表格格式顯示階層式資料。


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

樹狀表格需要一個 TreeNode 實例的集合作為 value,以及 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>

透過範本支援 headerfooter 插槽的自訂內容。


<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>

使用 paginatorTemplate 屬性自訂分頁器 UI。每個元素也可以使用您自己的 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>

透過新增 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>
    <template #paginatorcontainer="{ first, last, page, pageCount, prevPageCallback, nextPageCallback, totalRecords }">
        <div class="flex items-center gap-4 border border-primary bg-transparent rounded-full w-full py-1 px-2 justify-between">
            <Button icon="pi pi-chevron-left" rounded text @click="prevPageCallback" :disabled="page === 0" />
            <div class="text-color font-medium">
                <span class="hidden sm:block">Showing {{ first }} to {{ last }} of {{ totalRecords }}</span>
                <span class="block sm:hidden">Page {{ page + 1 }} of {{ pageCount }}</span>
            </div>
            <Button icon="pi pi-chevron-right" rounded text @click="nextPageCallback" :disabled="page === pageCount - 1" />
        </div>
    </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>

可以透過將 sortMode 定義為 multiple 來對多個欄位進行排序。此模式需要按下 meta 鍵(例如 )才能點擊標頭。


<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 時,第三次點擊會從欄位中移除排序。


<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>

透過將 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>

單一節點選取透過將 selectionMode 設定為 single 以及 selectionKeys 屬性來管理選取值繫結進行配置。

預設情況下,需要按下 meta 鍵(例如 )才能取消選取節點,但是可以透過停用 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>

透過將 selectionMode 設定為 multiple,可以選取多個節點。預設情況下,在多重選取模式下,不需要按下 meta 鍵(例如 )即可新增到現有選取範圍。當存在選用的 metaKeySelection 時,會以需要按下 meta 鍵才能選取新節點的方式變更行為。請注意,在觸控式裝置中,樹狀表格會始終忽略 meta 鍵。

在多重選取模式下,值繫結應為鍵值對,其中鍵是節點鍵,而值是布林值,用於指示選取。


<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>

透過將 selectionMode 配置為 checkbox,可以透過核取方塊選取多個節點。

在核取方塊選取模式下,值繫結應為鍵值對,其中鍵(或 dataKey)是節點鍵,而值是一個物件,該物件具有 checkedpartialChecked 屬性,以表示節點的勾選狀態。


{
    '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>

樹狀表格提供 nodeSelectnodeUnselect 事件以偵聽選取事件。


<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>

延遲模式對於處理大型資料集非常方便,而不是載入整個資料,而是每次發生 pagingsortingfiltering 時呼叫相應的回呼來載入小區塊的資料。以下範例使用記憶體清單和逾時來模擬網路連線,以模仿從遠端資料來源延遲載入資料。

啟用 lazy 屬性並透過執行投射查詢將邏輯列數指派給 totalRecords 是實作的關鍵要素,以便分頁器顯示 UI,假設實際存在 totalRecords 大小的記錄,儘管實際上它們不在頁面上,僅存在於目前頁面上顯示的記錄。

此外,只應載入根元素,可以使用 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>

新增 scrollable 屬性以及資料檢視區的 scrollHeight 可以使用固定標頭啟用垂直滾動。


<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 屬性在水平滾動期間固定欄位。位置透過 alignFrozen 定義,可以是 leftright


<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>

columnResizeMode 設定為 expand 也會變更表格寬度。


<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>

可以使用動態欄位實作基於條件的欄位可見性,在此範例中,多選下拉選單用於管理可見欄位。


<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>

樹狀表格透過 contextMenu 事件與上下文選單獨家整合,以在右鍵按一下時開啟選單,同時使用 contextMenuSelection 屬性和 row-contextmenu 事件來透過選單控制選取。


<ContextMenu ref="cm" :model="menuModel" @hide="selectedNode = null" />
<TreeTable v-model:contextMenuSelection="selectedNode" :value="nodes" contextMenu @row-contextmenu="onRowContextMenu" 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>

螢幕閱讀器

資料表格使用 treegrid 元素,可以使用 tableProps 選項擴充其屬性。此屬性允許傳遞 aria 角色和屬性,例如 aria-labelaria-describedby,以定義讀取器的表格。表格的預設角色為 table。標頭、主體和頁尾元素使用 rowgroup,列使用 row 角色,標頭儲存格具有 columnheader,而主體儲存格使用 cell 角色。可排序的標頭利用 aria-sort 屬性設定為「升序」或「降序」。

列元素管理狀態的 aria-expanded 以及定義階層的 aria-posinsetaria-setsizearia-level 屬性。

啟用選取時,會在列上將 aria-selected 設定為 true。在核取方塊模式下,樹狀表格元件會使用隱藏的原生核取方塊元素。

可編輯的儲存格使用自訂範本,因此如果需要,您需要手動管理 aria 角色和屬性。

分頁器是資料表格內部使用的獨立元件,請參閱 分頁器 以取得有關無障礙功能的更多資訊。

可排序標頭鍵盤支援

按鍵功能
tab在標頭之間移動。
enter排序欄位。
space排序欄位。

鍵盤支援

按鍵功能
tab當焦點進入元件時,如果有的話,會將焦點移至第一個選取的節點。如果沒有,則第一個元素會獲得焦點。如果焦點已經在元件內部,則會將焦點移至頁面 Tab 鍵順序中的下一個可聚焦元素。
Shift + Tab當焦點進入元件時,如果有的話,會將焦點移至最後一個選取的節點。如果沒有,則第一個元素會獲得焦點。如果焦點已經在元件內部,則會將焦點移至頁面 Tab 鍵順序中的上一個可聚焦元素。
enter選取焦點所在的樹狀節點。
space選取焦點所在的樹狀節點。
向下箭頭將焦點移至下一個樹狀節點。
向上箭頭將焦點移至上一個樹狀節點。
向右箭頭如果節點是關閉的,則開啟節點;否則將焦點移至第一個子節點。
向左箭頭如果節點是開啟的,則關閉節點;否則將焦點移至父節點。
Home將焦點移至第一個同級節點。
End將焦點移至最後一個同級節點。