Data Table Rendering

Inkline's Data Table columns and rows can be rendered using custom render helpers.

Inkline provides four ways to render data table fields:

  • Data Path (default)
  • Render function
  • Custom component
  • Scoped slot

Data Path

By default, table data is rendered using the path property of each column. The path property is a string (i.e. address.country) that points to the data that will be rendered for each row.

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Country', path: 'address.country' },
            ],
            rows: [
                { id: '1', name: 'Richard Hendricks', address: { city: 'Cupertino', country: 'United States' } },
                { id: '2', name: 'Bertram Gilfoyle', address: { city: 'Toronto', country: 'Canada' } },
                { id: '3', name: 'Dinesh Chugtai', address: { city: 'Lahore', country: 'Pakistan' } },
                { id: '4', name: 'Jared Dunn', address: { city: 'Berlin', country: 'Germany' } },
                { id: '5', name: 'Erlich Bachman', address: { city: 'Palo Alto', country: 'United States' } }
            ]
        }
    }
}
Data Table Path

Styling

You can provide classes and inline styles for both columns and rows. Column specific styles and classes will be applied to all <td> table data cells that are under a specific column:

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name', class: 'column-class' },
                { title: 'Country', path: 'address.country', style: { background: 'red' } },
            ],
            rows: [
                { id: '1', name: 'Richard Hendricks', address: { city: 'Cupertino', country: 'United States' } },
                { id: '2', name: 'Bertram Gilfoyle', address: { city: 'Toronto', country: 'Canada' } },
                { id: '3', name: 'Dinesh Chugtai', address: { city: 'Lahore', country: 'Pakistan' } },
                { id: '4', name: 'Jared Dunn', address: { city: 'Berlin', country: 'Germany' } },
                { id: '5', name: 'Erlich Bachman', address: { city: 'Palo Alto', country: 'United States' } }
            ]
        }
    }
}

Row styles and classes will be applied to the <tr> wrapper if specified using the row.config property.

You can also apply column specific classes and styles to a <td> table data cell of a row using row.config.columns[column.path]. A column path of * will apply to all child table data cells of the row.

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Country', path: 'address.country' },
            ],
            rows: [
                { 
                    id: '1', 
                    name: 'Richard Hendricks', 
                    address: { city: 'Cupertino', country: 'United States' },
                    config: {
                        class: 'row-class'
                    }
                },
                { 
                    id: '2', 
                    name: 'Bertram Gilfoyle', 
                    address: { city: 'Toronto', country: 'Canada' },
                    config: {
                        style: { 'font-weight': 'bold' }
                    }
                },
                { 
                    id: '3', 
                    name: 'Dinesh Chugtai', 
                    address: { city: 'Lahore', country: 'Pakistan' },
                    config: {
                        columns: {
                            '*': { class: [ 'column-class-a', 'column-class-b' ] }
                        }   
                    }
                },
                { 
                    id: '4', 
                    name: 'Jared Dunn', 
                    address: { city: 'Berlin', country: 'Germany' },
                    config: {
                        columns: {
                            name: { class: [ 'name-column-class' ] }
                        }   
                    }
                },
                { 
                    id: '5', 
                    name: 'Erlich Bachman', 
                    address: { city: 'Palo Alto', country: 'United States' },
                    config: {
                        columns: {
                            name: { style: { background: 'red' } }
                        }   
                    } 
                }
            ]
        }
    }
}

Render Function

By adding a function in the render property of the column definition, you can easily provide a way to manipulate data or display it differently. This is the simplest option, the perfect choice when working with simple strings.

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Address', path: 'address', render: (row) => `${row.address.city}, ${row.address.country}` },
            ],
            rows: [
                { id: '1', name: 'Richard Hendricks', address: { city: 'Cupertino', country: 'United States' } },
                { id: '2', name: 'Bertram Gilfoyle', address: { city: 'Toronto', country: 'Canada' } },
                { id: '3', name: 'Dinesh Chugtai', address: { city: 'Lahore', country: 'Pakistan' } },
                { id: '4', name: 'Jared Dunn', address: { city: 'Berlin', country: 'Germany' } },
                { id: '5', name: 'Erlich Bachman', address: { city: 'Palo Alto', country: 'United States' } }
            ]
        }
    }
}

Keep in mind that, by providing a custom render function, you will need to provide a custom sort function as well.

Data Table Render Function

Custom Component

You can render a table field using a component by specifying a component field in the table columns definition.

The rendered component will have table data passed to it using the row, column and index props.

export default {
    name: 'MyCustomComponent',
    props: ['row', 'column', 'index'],
    template: '<div>{{row.data}}</div>'
};
import MyCustomComponent from '@components/MyCustomComponent';

export default {
    data() {
        return {
            columns: [
                { title: 'Data', path: 'data', component: MyCustomComponent },
            ],
            rows: [
                { id: '1', data: 100 },
                { id: '2', data: 55 },
                { id: '3', data: 70 }
            ]
        }
    }
}

Here's an example for how to display a progress bar component on each row:

Data Table Custom Component

The component field can either contain the component object (most common) or the component tag as a string (i.e. my-custom-component), if it has been globally registered.

Scoped Slot

By providing a scoped row slot, you can render rows as you see fit.

<i-datatable :columns="columns" :rows="rows">
    <template v-slot:row="{ row, index }">
        <td align="right">{{index + 1}}</td>
        <td>{{row.name}}</td>
        <td>{{row.address.city}}, {{row.address.country}}</td>
    </template>
</i-datatable>

Keep in mind that, by providing a custom render function, you will need to provide a custom sort function as well.

Data Table Scoped Slot

Render Header Function

By adding a function in the renderHeader property of the column definition, you can easily manipulate table headers. This is the simplest option, the perfect choice when working with simple strings.

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Address', path: 'address', renderHeader: (column) => column.title.toUpperCase() },
            ],
            rows: [ ... ]
        }
    }
}
Data Table Render Header Function

Custom Header Component

You can render a table field using a component by specifying a headerComponent field in the table columns definition. This field will contain the component tag.

The rendered component will have table data passed to it using the row, column and index props.

export default {
    name: 'MyCustomComponent',
    props: ['column', 'index'],
    template: '<div>{{column.title}}</div>'
};
import MyCustomComponent from '@components/MyCustomComponent';

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Progress', path: 'progress', headerComponent: MyCustomComponent },
            ],
            rows: [
                { id: '1', name: 'Richard Hendricks', progress: 82 },
                { id: '2', name: 'Bertram Gilfoyle', progress: 55 },
                { id: '3', name: 'Dinesh Chugtai', progress: 70 },
                { id: '4', name: 'Jared Dunn', progress: 36 },
                { id: '5', name: 'Erlich Bachman', progress: 95 }
            ]
        }
    }
}

Here's a practical example where the header component contains a dropdown:

Data Table Custom Header Component

The headerComponent field can either contain the component object (most common) or the component tag as a string (i.e. my-custom-component), if it has been globally registered.

Scoped Header Slot

By providing a scoped header slot, you can render the datatable header as you see fit.

<i-datatable :columns="columns" :rows="rows">
    <template v-slot:header="{ sortBy }">
        <td class="_text-right">No.</td>
        <td>Name</td>
        <td>Country</td>
    </template>
</i-datatable>

Keep in mind that, by providing a custom render function, you will need to provide a custom sort function as well.

Data Table Scoped Header Slot

Header Wrapper Slot

By providing a scoped header-wrapper slot, you can render the datatable search, entries selector and pagination as you see fit.

<i-datatable :columns="columns" :rows="rows">
    <template v-slot:header-wrapper="{ rowsFrom, rowsTo, rowsCount, page, rowsPerPage, filter, onPageChange, onRowsPerPageChange, onFilterChange }">
        <i-input @input="onFilterChange" placeholder="Search.." />
        <div>
            <i-button :active="rowsPerPage === 10" @click="onRowsPerPageChange(10)">10</i-button>
            <i-button :active="rowsPerPage === 25" @click="onRowsPerPageChange(25)">25</i-button>
            <i-button :active="rowsPerPage === 50" @click="onRowsPerPageChange(50)">50</i-button>
        </div>
    </template>
</i-datatable>
Data Table Header Wrapper Slot

By adding a function in the renderFooter property of the column definition, you can easily manipulate table footers. This is the simplest option, the perfect choice when working with simple strings.

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Address', path: 'address', renderFooter: (column) => column.title.toUpperCase() },
            ],
            rows: [ ... ]
        }
    }
}
Data Table Render Header Function

You can render a table field using a component by specifying a footerComponent field in the table columns definition. This field will contain the component tag.

The rendered component will have table data passed to it using the row, column and index props.

export default {
    name: 'MyCustomComponent',
    props: ['column', 'index'],
    template: '<div>{{column.title}}</div>'
};
import MyCustomComponent from '@components/MyCustomComponent';

export default {
    data() {
        return {
            columns: [
                { title: 'Name', path: 'name' },
                { title: 'Progress', path: 'progress', footerComponent: MyCustomComponent },
            ],
            rows: [
                { id: '1', name: 'Richard Hendricks', progress: 82 },
                { id: '2', name: 'Bertram Gilfoyle', progress: 55 },
                { id: '3', name: 'Dinesh Chugtai', progress: 70 },
                { id: '4', name: 'Jared Dunn', progress: 36 },
                { id: '5', name: 'Erlich Bachman', progress: 95 }
            ]
        }
    }
}

Here's a practical example where the header component contains a dropdown:

Data Table Custom Footer Component

The footerComponent field can either contain the component object (most common) or the component tag as a string (i.e. my-custom-component), if it has been globally registered.

By providing a scoped footer slot, you can render the datatable footer as you see fit.

<i-datatable :columns="columns" :rows="rows">
    <template slot="footer">
        <td class="_text-right">No.</td>
        <td>Name</td>
        <td>Country</td>
    </template>
</i-datatable>

Keep in mind that, by providing a custom render function, you will need to provide a custom sort function as well.

Data Table Scoped Footer Slot

By providing a scoped footer-wrapper slot, you can render the datatable search, entries selector and pagination as you see fit.

<i-datatable :columns="columns" :rows="rows">
    <template v-slot:footer-wrapper="{ rowsFrom, rowsTo, rowsCount, page, rowsPerPage, filter, onPageChange, onRowsPerPageChange, onFilterChange }">
        <i-input @input="onFilterChange" placeholder="Search.." />
        <div>
            <i-button :active="rowsPerPage === 10" @click="onRowsPerPageChange(10)">10</i-button>
            <i-button :active="rowsPerPage === 25" @click="onRowsPerPageChange(25)">25</i-button>
            <i-button :active="rowsPerPage === 50" @click="onRowsPerPageChange(50)">50</i-button>
        </div>
    </template>
</i-datatable>
Data Table Footer Wrapper Slot