feat(data-table): support empty table body columns

This commit is contained in:
Eric Liu 2020-10-26 11:55:58 -07:00
commit 3c02829e73
7 changed files with 299 additions and 238 deletions

View file

@ -990,8 +990,8 @@ import { DataTable } from "carbon-components-svelte";
### Props ### Props
| Prop name | Type | Default value | Description | | Prop name | Type | Default value | Description |
| :------------- | :----------------------------------------------------------------------------------------------- | :------------ | :--------------------------------------------------------------------------------------------------------------- | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :------------ | :--------------------------------------------------------------------------------------------------------------- |
| headers | <code>{key: string; value: string; display?: (item) => string; sort?: (a, b) => number}[]</code> | `[]` | Specify the data table headers. | | headers | <code>{key: string; value: string; display?: (item) => string; sort?: (a, b) => number; empty?: boolean; columnMenu?: boolean; }[]</code> | `[]` | Specify the data table headers. |
| rows | <code>Object[]</code> | `[]` | Specify the rows the data table should render. keys defined in `headers` are used for the row ids. | | rows | <code>Object[]</code> | `[]` | Specify the rows the data table should render. keys defined in `headers` are used for the row ids. |
| size | <code>"compact" &#124; "short" &#124; "tall"</code> | -- | Set the size of the data table. | | size | <code>"compact" &#124; "short" &#124; "tall"</code> | -- | Set the size of the data table. |
| title | <code>string</code> | `""` | Specify the title of the data table. | | title | <code>string</code> | `""` | Specify the title of the data table. |

View file

@ -2532,7 +2532,7 @@
{ {
"kind": "let", "kind": "let",
"value": "[]", "value": "[]",
"type": "{key: string; value: string; display?: (item) => string; sort?: (a, b) => number}[]", "type": "{key: string; value: string; display?: (item) => string; sort?: (a, b) => number; empty?: boolean; columnMenu?: boolean; }[]",
"description": "Specify the data table headers" "description": "Specify the data table headers"
} }
], ],
@ -2677,14 +2677,14 @@
{ {
"attributes": [ "attributes": [
{ {
"start": 7574, "start": 7728,
"end": 7592, "end": 7746,
"type": "Attribute", "type": "Attribute",
"name": "name", "name": "name",
"value": [ "value": [
{ {
"start": 7580, "start": 7734,
"end": 7591, "end": 7745,
"type": "Text", "type": "Text",
"raw": "cell-header", "raw": "cell-header",
"data": "cell-header" "data": "cell-header"
@ -2692,27 +2692,27 @@
] ]
}, },
{ {
"start": 7593, "start": 7747,
"end": 7610, "end": 7764,
"type": "Attribute", "type": "Attribute",
"name": "header", "name": "header",
"value": [ "value": [
{ {
"start": 7601, "start": 7755,
"end": 7609, "end": 7763,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 7602, "start": 7756,
"end": 7608, "end": 7762,
"loc": { "loc": {
"start": { "start": {
"line": 265, "line": 268,
"column": 46 "column": 48
}, },
"end": { "end": {
"line": 265, "line": 268,
"column": 52 "column": 54
} }
}, },
"name": "header" "name": "header"
@ -2723,51 +2723,51 @@
], ],
"children": [ "children": [
{ {
"start": 7611, "start": 7765,
"end": 7625, "end": 7779,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "MemberExpression", "type": "MemberExpression",
"start": 7612, "start": 7766,
"end": 7624, "end": 7778,
"loc": { "loc": {
"start": { "start": {
"line": 265, "line": 268,
"column": 56 "column": 58
}, },
"end": { "end": {
"line": 265, "line": 268,
"column": 68 "column": 70
} }
}, },
"object": { "object": {
"type": "Identifier", "type": "Identifier",
"start": 7612, "start": 7766,
"end": 7618, "end": 7772,
"loc": { "loc": {
"start": { "start": {
"line": 265, "line": 268,
"column": 56 "column": 58
}, },
"end": { "end": {
"line": 265, "line": 268,
"column": 62 "column": 64
} }
}, },
"name": "header" "name": "header"
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 7619, "start": 7773,
"end": 7624, "end": 7778,
"loc": { "loc": {
"start": { "start": {
"line": 265, "line": 268,
"column": 63 "column": 65
}, },
"end": { "end": {
"line": 265, "line": 268,
"column": 68 "column": 70
} }
}, },
"name": "value" "name": "value"
@ -2786,14 +2786,14 @@
{ {
"attributes": [ "attributes": [
{ {
"start": 10621, "start": 11125,
"end": 10632, "end": 11136,
"type": "Attribute", "type": "Attribute",
"name": "name", "name": "name",
"value": [ "value": [
{ {
"start": 10627, "start": 11131,
"end": 10631, "end": 11135,
"type": "Text", "type": "Text",
"raw": "cell", "raw": "cell",
"data": "cell" "data": "cell"
@ -2801,27 +2801,27 @@
] ]
}, },
{ {
"start": 10633, "start": 11137,
"end": 10644, "end": 11148,
"type": "Attribute", "type": "Attribute",
"name": "row", "name": "row",
"value": [ "value": [
{ {
"start": 10638, "start": 11142,
"end": 10643, "end": 11147,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 10639, "start": 11143,
"end": 10642, "end": 11146,
"loc": { "loc": {
"start": { "start": {
"line": 346, "line": 357,
"column": 38 "column": 40
}, },
"end": { "end": {
"line": 346, "line": 357,
"column": 41 "column": 43
} }
}, },
"name": "row" "name": "row"
@ -2830,27 +2830,27 @@
] ]
}, },
{ {
"start": 10645, "start": 11149,
"end": 10658, "end": 11162,
"type": "Attribute", "type": "Attribute",
"name": "cell", "name": "cell",
"value": [ "value": [
{ {
"start": 10651, "start": 11155,
"end": 10657, "end": 11161,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 10652, "start": 11156,
"end": 10656, "end": 11160,
"loc": { "loc": {
"start": { "start": {
"line": 346, "line": 357,
"column": 51 "column": 53
}, },
"end": { "end": {
"line": 346, "line": 357,
"column": 55 "column": 57
} }
}, },
"name": "cell" "name": "cell"
@ -2861,86 +2861,86 @@
], ],
"children": [ "children": [
{ {
"start": 10659, "start": 11163,
"end": 10676, "end": 11182,
"type": "Text", "type": "Text",
"raw": "\n ", "raw": "\n ",
"data": "\n " "data": "\n "
}, },
{ {
"start": 10676, "start": 11182,
"end": 10742, "end": 11248,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "ConditionalExpression", "type": "ConditionalExpression",
"start": 10677, "start": 11183,
"end": 10741, "end": 11247,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 17 "column": 19
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 81 "column": 83
} }
}, },
"test": { "test": {
"type": "MemberExpression", "type": "MemberExpression",
"start": 10677, "start": 11183,
"end": 10695, "end": 11201,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 17 "column": 19
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 35 "column": 37
} }
}, },
"object": { "object": {
"type": "MemberExpression", "type": "MemberExpression",
"start": 10677, "start": 11183,
"end": 10687, "end": 11193,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 17 "column": 19
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 27 "column": 29
} }
}, },
"object": { "object": {
"type": "Identifier", "type": "Identifier",
"start": 10677, "start": 11183,
"end": 10684, "end": 11190,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 17 "column": 19
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 24 "column": 26
} }
}, },
"name": "headers" "name": "headers"
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 10685, "start": 11191,
"end": 10686, "end": 11192,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 25 "column": 27
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 26 "column": 28
} }
}, },
"name": "j" "name": "j"
@ -2950,16 +2950,16 @@
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 10688, "start": 11194,
"end": 10695, "end": 11201,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 28 "column": 30
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 35 "column": 37
} }
}, },
"name": "display" "name": "display"
@ -2969,74 +2969,74 @@
}, },
"consequent": { "consequent": {
"type": "CallExpression", "type": "CallExpression",
"start": 10698, "start": 11204,
"end": 10728, "end": 11234,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 38 "column": 40
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 68 "column": 70
} }
}, },
"callee": { "callee": {
"type": "MemberExpression", "type": "MemberExpression",
"start": 10698, "start": 11204,
"end": 10716, "end": 11222,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 38 "column": 40
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 56 "column": 58
} }
}, },
"object": { "object": {
"type": "MemberExpression", "type": "MemberExpression",
"start": 10698, "start": 11204,
"end": 10708, "end": 11214,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 38 "column": 40
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 48 "column": 50
} }
}, },
"object": { "object": {
"type": "Identifier", "type": "Identifier",
"start": 10698, "start": 11204,
"end": 10705, "end": 11211,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 38 "column": 40
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 45 "column": 47
} }
}, },
"name": "headers" "name": "headers"
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 10706, "start": 11212,
"end": 10707, "end": 11213,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 46 "column": 48
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 47 "column": 49
} }
}, },
"name": "j" "name": "j"
@ -3046,16 +3046,16 @@
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 10709, "start": 11215,
"end": 10716, "end": 11222,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 49 "column": 51
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 56 "column": 58
} }
}, },
"name": "display" "name": "display"
@ -3066,46 +3066,46 @@
"arguments": [ "arguments": [
{ {
"type": "MemberExpression", "type": "MemberExpression",
"start": 10717, "start": 11223,
"end": 10727, "end": 11233,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 57 "column": 59
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 67 "column": 69
} }
}, },
"object": { "object": {
"type": "Identifier", "type": "Identifier",
"start": 10717, "start": 11223,
"end": 10721, "end": 11227,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 57 "column": 59
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 61 "column": 63
} }
}, },
"name": "cell" "name": "cell"
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 10722, "start": 11228,
"end": 10727, "end": 11233,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 62 "column": 64
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 67 "column": 69
} }
}, },
"name": "value" "name": "value"
@ -3118,46 +3118,46 @@
}, },
"alternate": { "alternate": {
"type": "MemberExpression", "type": "MemberExpression",
"start": 10731, "start": 11237,
"end": 10741, "end": 11247,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 71 "column": 73
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 81 "column": 83
} }
}, },
"object": { "object": {
"type": "Identifier", "type": "Identifier",
"start": 10731, "start": 11237,
"end": 10735, "end": 11241,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 71 "column": 73
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 75 "column": 77
} }
}, },
"name": "cell" "name": "cell"
}, },
"property": { "property": {
"type": "Identifier", "type": "Identifier",
"start": 10736, "start": 11242,
"end": 10741, "end": 11247,
"loc": { "loc": {
"start": { "start": {
"line": 347, "line": 358,
"column": 76 "column": 78
}, },
"end": { "end": {
"line": 347, "line": 358,
"column": 81 "column": 83
} }
}, },
"name": "value" "name": "value"
@ -3168,8 +3168,8 @@
} }
}, },
{ {
"start": 10742, "start": 11248,
"end": 10757, "end": 11265,
"type": "Text", "type": "Text",
"raw": "\n ", "raw": "\n ",
"data": "\n " "data": "\n "
@ -3184,14 +3184,14 @@
{ {
"attributes": [ "attributes": [
{ {
"start": 11293, "start": 11821,
"end": 11312, "end": 11840,
"type": "Attribute", "type": "Attribute",
"name": "name", "name": "name",
"value": [ "value": [
{ {
"start": 11299, "start": 11827,
"end": 11311, "end": 11839,
"type": "Text", "type": "Text",
"raw": "expanded-row", "raw": "expanded-row",
"data": "expanded-row" "data": "expanded-row"
@ -3199,26 +3199,26 @@
] ]
}, },
{ {
"start": 11313, "start": 11841,
"end": 11324, "end": 11852,
"type": "Attribute", "type": "Attribute",
"name": "row", "name": "row",
"value": [ "value": [
{ {
"start": 11318, "start": 11846,
"end": 11323, "end": 11851,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 11319, "start": 11847,
"end": 11322, "end": 11850,
"loc": { "loc": {
"start": { "start": {
"line": 366, "line": 378,
"column": 48 "column": 48
}, },
"end": { "end": {
"line": 366, "line": 378,
"column": 51 "column": 51
} }
}, },

View file

@ -318,7 +318,7 @@ The slot name for the table header cells is `"cell-header"`.
<ToolbarSearch /> <ToolbarSearch />
<ToolbarMenu> <ToolbarMenu>
<ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem> <ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem>
<ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">API Documentation</ToolbarMenuItem> <ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">API documentation</ToolbarMenuItem>
<ToolbarMenuItem danger>Stop all</ToolbarMenuItem> <ToolbarMenuItem danger>Stop all</ToolbarMenuItem>
</ToolbarMenu> </ToolbarMenu>
<Button>Create balancer</Button> <Button>Create balancer</Button>
@ -385,7 +385,7 @@ The slot name for the table header cells is `"cell-header"`.
<ToolbarSearch /> <ToolbarSearch />
<ToolbarMenu> <ToolbarMenu>
<ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem> <ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem>
<ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">API Documentation</ToolbarMenuItem> <ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">API documentation</ToolbarMenuItem>
<ToolbarMenuItem danger>Stop all</ToolbarMenuItem> <ToolbarMenuItem danger>Stop all</ToolbarMenuItem>
</ToolbarMenu> </ToolbarMenu>
<Button>Create balancer</Button> <Button>Create balancer</Button>
@ -668,6 +668,15 @@ The slot name for the table header cells is `"cell-header"`.
]}" ]}"
/> />
### Empty column with overflow menu
Some use cases require an empty column in the table body without a corresponding table header.
For an object in the `headers` array, set `empty` to `true` to render an empty column.
In the following example, each row in the sortable data table has an overflow menu. There isn't a separate, useless table header column for the overflow menu.
<FileSource src="/framed/DataTable/DataTableAppendColumns" />
### Selectable ### Selectable

View file

@ -0,0 +1,38 @@
<script>
import {
DataTable,
OverflowMenu,
OverflowMenuItem,
} from "carbon-components-svelte";
const headers = [
{ key: "name", value: "Name" },
{ key: "port", value: "Port" },
{ key: "rule", value: "Rule" },
{ key: "overflow", empty: true },
];
const rows = [
{ id: "a", name: "Load Balancer 3", port: 3000, rule: "Round robin" },
{ id: "b", name: "Load Balancer 1", port: 443, rule: "Round robin" },
{ id: "c", name: "Load Balancer 2", port: 80, rule: "DNS delegation" },
{ id: "d", name: "Load Balancer 6", port: 3000, rule: "Round robin" },
{ id: "e", name: "Load Balancer 4", port: 443, rule: "Round robin" },
{ id: "f", name: "Load Balancer 5", port: 80, rule: "DNS delegation" },
];
</script>
<DataTable sortable headers="{headers}" rows="{rows}">
<span slot="cell" let:cell>
{#if cell.key === 'overflow'}
<OverflowMenu open flipped>
<OverflowMenuItem text="Restart" />
<OverflowMenuItem
href="https://cloud.ibm.com/docs/loadbalancer-service"
text="API documentation"
/>
<OverflowMenuItem danger text="Stop" />
</OverflowMenu>
{:else}{cell.value}{/if}
</span>
</DataTable>

View file

@ -41,7 +41,7 @@
<ToolbarMenu> <ToolbarMenu>
<ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem> <ToolbarMenuItem primaryFocus>Restart all</ToolbarMenuItem>
<ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service"> <ToolbarMenuItem href="https://cloud.ibm.com/docs/loadbalancer-service">
API Documentation API documentation
</ToolbarMenuItem> </ToolbarMenuItem>
<ToolbarMenuItem danger>Stop all</ToolbarMenuItem> <ToolbarMenuItem danger>Stop all</ToolbarMenuItem>
</ToolbarMenu> </ToolbarMenu>

View file

@ -1,7 +1,7 @@
<script> <script>
/** /**
* Specify the data table headers * Specify the data table headers
* @type {{key: string; value: string; display?: (item) => string; sort?: (a, b) => number}[]} [headers=[]] * @type {{ key: string; value: string; display?: (item) => string; sort?: (a, b) => number; empty?: boolean; columnMenu?: boolean; }[]} [headers=[]]
*/ */
export let headers = []; export let headers = [];
@ -247,6 +247,9 @@
</th> </th>
{/if} {/if}
{#each headers as header, i (header.key)} {#each headers as header, i (header.key)}
{#if header.empty}
<th scope="col"></th>
{:else}
<TableHeader <TableHeader
on:click="{() => { on:click="{() => {
dispatch('click', { header }); dispatch('click', { header });
@ -264,6 +267,7 @@
> >
<slot name="cell-header" header="{header}">{header.value}</slot> <slot name="cell-header" header="{header}">{header.value}</slot>
</TableHeader> </TableHeader>
{/if}
{/each} {/each}
</TableRow> </TableRow>
</TableHead> </TableHead>
@ -337,6 +341,13 @@
</td> </td>
{/if} {/if}
{#each row.cells as cell, j (cell.key)} {#each row.cells as cell, j (cell.key)}
{#if headers[j].empty}
<td class:bx--table-column-menu="{headers[j].columnMenu}">
<slot name="cell" row="{row}" cell="{cell}">
{headers[j].display ? headers[j].display(cell.value) : cell.value}
</slot>
</td>
{:else}
<TableCell <TableCell
on:click="{() => { on:click="{() => {
dispatch('click', { row, cell }); dispatch('click', { row, cell });
@ -347,6 +358,7 @@
{headers[j].display ? headers[j].display(cell.value) : cell.value} {headers[j].display ? headers[j].display(cell.value) : cell.value}
</slot> </slot>
</TableCell> </TableCell>
{/if}
{/each} {/each}
</TableRow> </TableRow>

2
types/index.d.ts vendored
View file

@ -798,6 +798,8 @@ export class DataTable extends CarbonSvelteComponent {
value: string; value: string;
display?: (item) => string; display?: (item) => string;
sort?: (a, b) => number; sort?: (a, b) => number;
empty?: boolean;
columnMenu?: boolean;
}[]; }[];
/** /**