# j-DataTable

> BETA: This component is targeted for SPA and server-side listing.

Framework: jcomponent20
Product: jComponent 20 (jcomponent@20)
Language: en
Content-SHA256: 07b9c16945d8a7effe1760ca889312a66c92c690828035a97358d42bc9132576
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: components@910ed1a86f6e72b4f031d3ad0dc7844f9fc5cb8e
Review: not-recorded

__BETA__: This component is targeted for SPA and server-side listing.

- supports pagination
- needed `bootstrap` grid system
- supports sorting
- supports vertical/horizontal scrolling
- responsive
- supports __dark mode__

__Data-source__ needs to contain:

```js
{
	cols: [{ name: 'id', ... }], // optional, can be defined inline in HTML
    items: [{ name: 'Row 1' }, { name: 'Row 2' }, ...] // items
    page: 1,    // current pages
    pages: 30,  // count of pages
    limit: 5,   // items limit per page
    count: 150  // count of items in DB
}
```

__Configuration__:

- `pluralizepages {String}` pluralization for pages (optional, default: `# pages,# page,# pages,# pages`)
- `pluralizeitems {String}` pluralization for items (optional, default: `# items,# item,# items,# items`)
- `height {Number/String}` height of grid, supported values: `auto` (default), __NEW__ `fluid`, `parent` or `NUMBER` as height or `selector` for jQuery.closest()
- __NEW__ `minheight {Number}` minimal height of grid, works with `fluid` and `auto` height (default: `300`)
- __NEW__ `parent {String}` selector for `auto` height option (default: `window`)
- `margin {Number}` a top margin for height (optional, default: `0`)
- `click {String}` a link to `function(row, grid, row_el)`, it's executed if the user clicks on a row
- `highlight {Boolean}` each selected row (after `click`) will be highlighted (default: `false`)
- `unhighlight {Boolean}` enables `undo highlighting` of selected row (default: `true`)
- `checked {String}` `path` to a variable or path to `function(rows, grid)` is executed if the user selected/checked some rows
- `autoselect {Boolean}` enables auto-select of first row in grid, it performs `EXEC(config.click)`, default: `false`
- `exec {String}` a link to `function(type, page, sort)` for server-side operations only (it disables client-side sorting & filtering), supported types: `refresh` or `page`
- `changed {String}` `path` to a variable or path to `function(rows, grid)` is executed if the user changed some rows
- `dblclick {String}` a link to `function(row, grid, row_el)` method, it's executed if the user double-clicks on a row
- `noborder {Boolean}` can disable a border around the grid (default: `false`)
- `colwidth {Number}` a default width for columns (default: `150`)
- `editable {String}` a link to `function(opt)` when the user performs editing
- `contextmenu {String}` a link to `function(e, grid)` when the user raises context menu

__Column properties__:

- `name {String}` a name of field in the row object
- `text {String}` a column label, text with `.fa fa-home` will render FontAwesome icon
- `width {Number}` a column width (optional, default `config.colwidth`)
- `align {String}` can be `center` or `right` (optional, default: `left`)
- `template {String}` can be a Tangular template and the model is the entire object of row
- `sort {Boolean}` enables sorting (optional, default: `false`)
- `format {String/Number}` can be used for date and numbers (count of decimals) field (optional), e.g. `dd.MM.yyyy`
- `currency {String}` a currency formatter, just add a currency
- `class {String}` optional, a custom column class name
- `empty {String/Boolean}` optional, can rewrite empty value with the value defined in empty field (`true` value uses `---` as a default value)
- `type {String}` optional, can contain a data-type (`boolean`, `date` or `number`) for the field
- `editable {Boolean}` enables editing

__Methods__:

- `component.redrawrow(row_object/index)` redraws row or __NEW__: replaces+redraws `row_object` with a new `new_object_row`
- `component.clear()` clears all changes
- `component.select(row)` selects `row` must be the same object as in data-source
- `component.rebind(columnsdeclaration)` the method rebinds the schema
- __NEW__: `component.reload()` executes `config.exec` with the current filter and sorting
- __NEW__: `component.empty()` empties all rows

__Good to know__:

- `SET('link.to.data', data, 'noscroll')` --> `noscroll` type disables reseting of scrolling

__How to extend a class of row?__

- look to the `{{ if active` line, it extends a class of row by adding `dg-active-class` if the `active` will be valid

```js
[
	'{{ if active }} dg-active-class{{ fi }}',
	{ name: 'name', text: 'Name', width: 200 },
	// other columns ...
]
```

Use it with `<ui-component name="datatable">`. When the component is not loaded yet, jComponent downloads it on first use from the address in `DEF.fallback` (the Componentator CDN by default). Author: Peter Širka. Source: the Componentator components repository, MIT license.

```html example.html
<div style="width:500px;height:400px">
	<ui-component name="datatable" path="data" config="highlight:1;exec:paginate;editable:editable;checked:checked;margin:22">
		<script type="text/html">
			[
				{ name: 'name', text: 'Opportunity name', width: 200, sort: 1, editable: 1 },
				{ name: 'value', text: 'Value', width: 100, sort: 1, type: 'number', format: 2 },
				{ name: 'status', text: 'Status', width: 100, editable: 1 },
				{ name: 'owner', text: 'Owner', width: 200 },
				{ name: 'newsletter', text: 'Newsletter', width: 100, type: 'boolean' },
				{ name: 'date', text: 'Date', width: 200, sort: 1, type: 'date', format: 'yyyy-MM-dd' }
			]
		</script>
	</ui-component>
</div>

<script>

	function checked(rows) {
		console.log(rows);
	}

	function editable(opt) {
		// opt.row
		// opt.col
		// opt.value
		// opt.next(NEW_VALUE);
		opt.next(opt.value + ' (modified)');
	}

	function paginate(type, page, sort) {
		console.log('Page:', page, 'sort:', sort);
	}

		var data = {};

		data.items = [];
		data.pages = 53;
		data.page = 3;

		// data.cols.push({ name: 'name', text: 'Opportunity name', width: 200, sort: true });
		// data.cols.push({ name: 'value', text: 'Value', width: 100, sort: true });
		// data.cols.push({ name: 'status', text: 'Status', width: 100 });
		// data.cols.push({ name: 'owner', text: 'Owner', width: 200 });
		// data.cols.push({ name: 'date', text: 'Date', width: 200, sort: true });

		for (var i = 0; i < 50; i++)
			data.items.push({ name: GUID(20), value: Math.random() * 1000 >> 0, status: GUID(10), owner: 'Peter Širka', newsletter: i % 3 === 0, date: NOW });
</script>
```
