Security News
Create React App Officially Deprecated Amid React 19 Compatibility Issues
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
gridy-grid
Advanced tools
Web Components based data grid (table).
If you are looking for web components based widgets collection check out skinny-widgets project.
As for the moment you must install one of theme packages by your choice, e.g. gridy-grid-default, gridy-grid-antd or gridy-grid-jquery in addition to this package and specify the chosen theme as sk-config or gridy-grid element's attribute.
Prebuilt bundle can be found here: gridy-grid-bundle
npm i gridy-grid gridy-grid-jquery sk-theme-jquery --save
Bundles that are prebuilt js and html code for static plug can be found in gridy-grid-bundle package
Let's see the example for the data loaded from json within javascript execution context.
<gridy-table base-path="/node_modules/gridy-grid/src" theme="jquery" id="gridyTable"></gridy-table>
<script type="module">
import { GridyTable } from '/node_modules/gridy-grid/src/table/gridy-table.js';
import { DataSourceLocal } from '/node_modules/gridy-grid/src/datasource/data-source-local.js';
let dataSource = new DataSourceLocal();
dataSource.fields = [
{ title: 'Title', path: '$.title' },
{ title: 'Price', path: '$.price' }
];
let data = [];
for (let i = 0; i < 10; i++) {
data.push({ title: 'row' + i, price: 100 * i })
}
// local datasource data load should be called explicitly
gridyTable.dataSource = dataSource;
customElements.define('gridy-table', GridyTable);
dataSource.loadData(data);
</script>
GridyGrid is the container element that simplifies components configuration and instantiation. Just wrap your components with it and bind DataSource instance or use gridy-data-source element.
gridy-grid will instantiate and bind dataSource when found gridy-data-source subelement. Don't forget to start demo server to check outh the code sample below.
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.19.8/antd.css" />
<gridy-grid theme="antd" id="gridyGrid" base-path="/node_modules/gridy-grid/src" sort-field="$.title">
<gridy-data-source fields='[{ "title": "Title", "path": "$.title" },{ "title": "Price", "path": "$.price" }]'
datasource-type="ajax" url='http://127.0.0.1:8080/unpaged' datapath="$.data"></gridy-data-source>
<gridy-spinner></gridy-spinner>
<gridy-table-info id="gridyTableInfo"></gridy-table-info>
<gridy-filter id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
<gridy-table-info id="gridyTableInfo"></gridy-table-info>
</gridy-grid>
<gridy-data-source fields='[{ "title": "Title", "displayTitle": "Some title", "path": "$.title" },{ "title": "Price", "path": "$.price"},{ "title": "Created", "path": "$.created"}]'
req-type="POST" req-param-map='{"perPage": "per_page", "sortField": {"name": "sort_field", "type": "body"}}' datasource-type="ajax" url='http://127.0.0.1:8080/paged' back-paged data-path="$.data"></gridy-data-source>
datasource-type - attribute can have values either 'ajax' or 'local' (used when no value is defined) or any class
with name DataSource${type}
assigned to window
fields - row fields configuration json
data-path - json path for row data to be extracted
http-client-type - ajax only, used to switch between XmlHttpClient and FetchHttpClient or any custom ${Type}HttpClient assigned to window
http-client-cn - ajax only custom http client class name, completely overrides classname
http-client-options - ajax only custom http client class constructor args json
back-paged - ajax only defines if all data if fetched with one request or backend pagination and filtration is used.
Response may have the following payload (Note: data-path is set to "$.data"):
{"data":[{"field1": "FooBar11", "field2": 22}, ...], "page":2, "perPage":10, "totalResults": 16 }
and understand the following request parameters (that can be remapped with req-param-map attribute configuration) returning different pages:
?page=2&perPage=10
url - ajax only request url
req-type - request type, possible values: "GET", "POST", default: (node set -> "GET")
req-param-map - ajax only request parameter map json for backend pagination, in case your backend needs special parameter names, the following parameters can be used by dataSource: page, perPage, sortField, sortDirection. table-sort-field-id gridy-table element attribute can be used to specify sortField value from fields configuration property like name, title, path etc
req-headers - ajax only request headers json
resp-param-map - ajax only response paramter map json, value can be provided as property name or json path, fields supported: totalResults, sortField, sortDirection
<gridy-data-source fields='[{ "title": "Name", "path": "$.name", "name": "name" },{ "title": "Url", "path": "$.url", "name": "url"}]'
datasource-type="ajax" url='http://127.0.0.1:8080/view_paged' back-paged data-path="$.data" resp-param-map='{ "totalResults": "total" }'
></gridy-data-source>
title - more like field id
displayTitle - attribute and its equal json property displayTitle can be used to alter title in table headings, e.g. with localized labels
path json path relative to row
noRender any truable value prevents field from rendering in table
You can alter grid layout with own markup
<gridy-grid id="gridyGrid" base-path="/node_modules/gridy-grid/src" sort-field="$.title">
<style>
.gridy-heading {
display: flex;
width: 100%;
justify-content: space-between;
}
</style>
<div class="gridy-heading">
<gridy-table-info id="gridyTableInfo"></gridy-table-info>
<gridy-per-page id="gridyPerPage"></gridy-per-page>
</div>
<gridy-filter id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
</gridy-grid>
For local data source we may need less args:
<gridy-data-source fields='[{ "title": "Title", "path": "$.title" },{ "title": "Price", "path": "$.price" }]'
dataref="gridData"></gridy-data-source>
It's also possible to configure data-source with markup instead of attribute:
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.19.8/antd.css">
<gridy-grid theme="antd" id="gridyGrid" base-path="/node_modules/gridy-grid/src">
<gridy-data-source dataref="gridData">
<gridy-data-field title="Title" path="$.title"></gridy-data-field>
<gridy-data-field title="Price" path="$.price"></gridy-data-field>
</gridy-data-source>
<gridy-spinner></gridy-spinner>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
</gridy-grid>
You can load data programmatically by markup defined datasource:
<gridy-grid theme="jquery" id="gridyGrid" base-path="/node_modules/gridy-grid/src" sort-field="$.title">
<gridy-data-source fields='[{ "title": "Title", "path": "$.title" },{ "title": "Price", "path": "$.price" }]'
datapath="$.data"></gridy-data-source>
<gridy-spinner></gridy-spinner>
<gridy-table-info id="gridyTableInfo"></gridy-table-info>
<gridy-filter id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
<gridy-table-info id="gridyTableInfo"></gridy-table-info>
</gridy-grid>
<script type="module">
import { SkConfig } from './node_modules/sk-core/src/sk-config.js';
customElements.define('sk-config', SkConfig);
import { GridyGrid } from '/node_modules/gridy-grid/src/gridy-grid.js';
window.data = [];
for (let i = 0; i < 25; i++) {
window.data.push({ title: 'row' + i, price: 100 * i })
}
let grid = document.querySelector('#gridyGrid');
customElements.define('gridy-grid', GridyGrid);
grid.whenBootstraped(() => {
grid.dataSource.loadData(data);
});
</script>
And you are still free to instantiate and configure dataSource programmatically:
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.19.8/antd.css">
<gridy-grid theme="antd" id="gridyGrid">
<gridy-filter id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
</gridy-grid>
<style>
th.sort.sort-desc::after {
content: '▼';
}
th.sort.sort-asc::after {
content: '▲';
}
</style>
<script type="module">
import { GridyGrid } from '/node_modules/gridy-grid/src/gridy-grid.js';
import { DataSourceAjax } from '/node_modules/gridy-grid/src/datasource/data-source-ajax.js';
let dataSource = new DataSourceAjax();
dataSource.fields = [
{ title: 'Title', path: '$.title' },
{ title: 'Price', path: '$.price', fmt: (field, value, row) => `<b>$ ${value}</b>`, html: true }
];
dataSource.url = 'http://127.0.0.1:8080/paged';
let grid = document.querySelector('#gridyGrid');
grid.dataSource = dataSource;
customElements.define('gridy-grid', GridyGrid);
</script>
Without gridy-grid container you'll have to provider every element with configurations and link with the following attributes:
ds-ref - to specify DataSource element id/global name
pg-ref - to link table to pager
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.19.8/antd.css">
<gridy-data-source dataref="gridData" id="dataSource">
<gridy-data-field title="Title" path="$.title"></gridy-data-field>
<gridy-data-field title="Price" path="$.price"></gridy-data-field>
</gridy-data-source>
<gridy-table theme="antd" id="gridyGrid" base-path="/node_modules/gridy-grid/src" id="gridyTable"
ds-ref="dataSource" pg-ref="gridyPager" sort-field="$.title"></gridy-table>
<gridy-pager theme="antd" base-path="/node_modules/gridy-grid/src" id="gridyPager" ds-ref="dataSource"></gridy-pager>
<script type="module">
import { GridyTable } from '/node_modules/gridy-grid/src/table/gridy-table.js';
let data = [];
for (let i = 0; i < 25; i++) {
data.push({ title: 'row' + i, price: 100 * i })
}
window.gridData = data;
customElements.define('gridy-table', GridyTable);
</script>
Gridy elements can load common configuration attributes from special elements in DOM so you don't need to repeat them for each element, currently gridy-config and sk-config (from skinny-widgets) are supported. You can alternate config element lookup selector with config-sl attribute.
<sk-config
theme="antd"
base-path="/node_modules/gridy-grid/src"
lang="ru_RU"
id="myConfig"
></sk-config>
to use date filter you will have to install datepicker packages. Also filter package have to be installed or you will have to plug preloaded templates
npm i sk-datepicker sk-datepicker-antd gridy-filter-date
<sk-config
lang="ru" id="skConfig" theme="antd"></sk-config>
<gridy-grid theme="antd" id="gridyGrid">
<gridy-data-source dataref="gridData">
<gridy-data-field title="Title" path="$.title"></gridy-data-field>
<gridy-data-field title="Price" path="$.price"></gridy-data-field>
<gridy-data-field title="Created" path="$.created"></gridy-data-field>
</gridy-data-source>
<gridy-spinner></gridy-spinner>
<gridy-filter dri="date" filter-mode="ge" field-title="Created" id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable">
</gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
<gridy-table-info id="gridyTableInfo"></gridy-table-info>
</gridy-grid>
<script type="module">
import { GridyGrid } from '/node_modules/gridy-grid/src/gridy-grid.js';
import { SkDatePicker } from './node_modules/sk-datepicker/src/sk-datepicker.js';
let data = [];
for (let i = 0; i < 25; i++) {
let today = new Date();
today.setDate(today.getDate() + i);
data.push({title: 'row' + i, price: 100 * i, created: today.toLocaleDateString("en-US")})
}
let grid = document.querySelector('#gridyGrid');
grid.addEventListener('bootstrap', () => {
grid.dataSource.loadData(data);
grid.table.whenRendered(() => {
console.log('table rendered');
});
});
customElements.define('gridy-grid', GridyGrid);
customElements.define('sk-datepicker', SkDatePicker);
</script>
By default data is displayed without pagination.
gridy-grid element will enable pagination when gridy-pager element is found in internals or it has per-page configuration attribute specified by forwarding it to supported subelements.
You can generate some usual table markup with data by yourself and init Gridy Grid for it.
<gridy-table id="gridyTable" pgref="gridyPager" base-path="/node_modules/gridy-grid/src" theme="antd">
<table>
<tbody class="ant-table-tbody">
<tr><td>row hand 1</td><td><b>$ 0</b></td></tr>
<tr><td>row hand 2</td><td><b>$ 100</b></td></tr>
<tr><td>row hand 3</td><td><b>$ 100</b></td></tr>
<tr><td>row hand 4</td><td><b>$ 100</b></td></tr>
<tr><td>row hand 5</td><td><b>$ 100</b></td></tr>
</tbody>
</table>
</gridy-table>
<gridy-pager id="gridyPager" dsref="gridyTable.dataSource" base-path="/node_modules/gridy-grid/src" theme="antd"></gridy-pager>
<script type="module">
import { GridyTable } from '/node_modules/gridy-grid/src/table/gridy-table.js';
customElements.define('gridy-table', GridyTable);
</script>
or with datasource:
<gridy-grid id="gridyGrid" base-path="/node_modules/gridy-grid/src" sort-field="$.title">
<gridy-data-source fields='[{ "title": "Title", "path": "$.[0]" },{ "title": "Price", "path": "$.[1]"}]'></gridy-data-source>
<gridy-table selectable="multi" selection-emit="ctrl+click" theme="antd" id="gridyTable">
<table>
<tbody class="ant-table-tbody">
<tr><td>row hand 1</td><td>0</td></tr>
<tr><td>row hand 2</td><td>100</td></tr>
<tr><td>row hand 3</td><td>100</td></tr>
<tr><td>row hand 4</td><td>100</td></tr>
<tr><td>row hand 5</td><td>100</td></tr>
</tbody>
</table>
</gridy-table>
<gridy-pager id="gridyPager2"></gridy-pager>
</gridy-grid>
thead contents also can be parsed, but only for ds field props that are not defined
Attribute selectable will enable selection behaviour when added to gridy-grid or gridy-table element. When value is set as "multi" there will be possible to select multiple rows, when any other or no value - only one row.
selection-emit attribute choses how selection will be emited, e.g. on long click/tap or click, possible values: "tap" - select by long click/tap, "click", "ctrl+click", "shift+click", "alt+click" (default: no -> click)
time-to-select - time to select for tap mode in miliseconds, (default: 700x)
GridyTable properties selectedRow, selectedRows and prevSelectedRow store links to selected rows.
you can get link to rendered (visually present on table) table row by dataItem (data row mapped by field title) provided with rowByDataItem(dataIitem) gridy-table method
let gridyGrid = document.getElementById('gridyGrid');
let dataItem = {'title': 'foobar9', 'price': 600, 'created': '13.04.2022'};
let rowEl = gridyGrid.table.rowByDataItem(dataItem);
console.log(`row for ${JSON.stringify(dataItem)}`, rowEl);
You can either bind it with general event api using gridy-grid element or gridy-table and rely to path attribue values or use special property onrowclick or onhrowclick (for heading) for convenience:
gridyTable.onrowclick = function(event, row) {
console.log('rowclick', event, row, this);
};
onrowrclick is for right button mouse click handling
You can easily implement details pane with your own template.
<gridy-table id="gridyTable" row-pane>
</gridy-table>
<template id="tableRowPaneTpl">
<div>Price:</div><div>{{ price }}</div>
</template>
Row data mapped to field is exposed info template rendering context.
row-pane-tpl-path - template loading url, can be specified to anything if template predefined dom
row-state - preserve row pane state between paging and sorting operations (default: not set -> false)
You can specify any own td's attribute as value or lambda with attr options subset, e.g. you want to implement cell hover hint
dataSource.fields = [
{ title: 'Title', path: '$.title', attr: { title: (field, value) => `${field.title}` }},
{ title: 'Price', path: '$.price' }
];
rowattr can be also specified in the same way for tr element, beware multiple same attrs will overwrite each other
tplPath - path for cell template to render, html option is also recommended to be enabled with this parameter, row data (dataItem) and executed value are flatmapped to rendering context
calc - calculation map with fields to functions, that evaluted on page is rendered, the result is passed to fmt function by key. Here is the example you can add hashcode calculation by executing method from dataSource. The first (0) argument of evaluted function is dataItem and context is binded to dataSource. If you use sort in LocalDataSource and calc is provided as hashmap then first calculated key is taken to compare.
calculation cache is controlled by table-calc-cache attr for gridy-table or config element, define it to enable, rows
must have unique contents (e.g. has id
field) to have caching work properly
<gridy-data-source fields='[{ "title": "Hashcode", "name": "hashcode", "fmt": "{{ hash }}", "calc": { "hash": "return this.hashDataItem(arguments[0])" }}]'></gridy-data-source>
or
<gridy-data-source fields='[{ "title": "Hashcode", "name": "hashcode", "fmt": "return arguments[0].calc;", "calc": { "return this.hashDataItem(arguments[0])" }]'></gridy-data-source>
fmt - field attribute allows to have string templating with value and row field values are available in rendering context or evaluted callback (when you use javascript to configure fields). The args of this callback are: field, value, dataItem, rendered. To evalute html from fmt you should also add html: true attribute.
if fmt string starts with words 'return', it will be evaluted as function with the following map as argument { value: value, ...dataItem, ...calcs, rendered: rendered } with context binded to table component
<gridy-data-source fields='[{ "title": "Hashcode", "name": "hashcode", "fmt": "return arguments[0].hash;", "calc": { "hash": "return this.hashDataItem(arguments[0])" }}]'></gridy-data-source>
formatting result cache is controlled by table-fmt-cache attr for gridy-table or config element, define it to enable, rows
must have unique contents (e.g. has id
field) to have caching work properly
in case tplPath and fmt both specified they can do accumulative rendering, template rendering result is passed as rendered var to fmt method or 4th arg to function.
<gridy-grid id="itemsGrid">
<gridy-data-source fields='[{ "title": "", "path": "$.*", "fmt": "<sk-checkbox class=\"item-chk no-rowclick\" value=\"{{ value }}\"></sk-checkbox>", "html": "true"}, { "title": "Содержание", "path": "$.contents" },{ "title": "Исполнитель", "path": "$.executor" },{ "title": "Ответственный", "path": "$.responsible" },{ "title": "Время выполнения", "path": "$.unitsToComplete" }]'
datasource-type="DataSourceLocal" datapath="$.data"></gridy-data-source>
<gridy-table id="itemsTable"></gridy-table>
<gridy-pager id="itemsPager"></gridy-pager>
</gridy-grid>
hide column
<gridy-table id="gridyTable" stored-cfg='{"columns": {"Name": { "display": "none"}}}'></gridy-table>
set custom styles (in camel-case)
<gridy-table id="gridyTable" stored-cfg='{"columns": {"Name": {"style": {"color": "red"}}}}'></gridy-table>
set column attribute by it's name
<gridy-table id="gridyTable" stored-cfg='{"columns": {"Name": { "attr": {"attr": {"style": "color:red"}}}}'></gridy-table>
reorder columns
<gridy-table id="gridyTable" stored-cfg='{"columnsOrder": ["Color", "Value", "Name"]}'></gridy-table>
you can preset any instance property when specify in stored-props attr json
<gridy-grid id="gridyGrid" base-path="/node_modules/gridy-grid/src" sort-field="$.name" stored-cfg='{"curPageNum": "2"}' stored-props='["curPageNum"]'></gridy-grid>
To add context menu with settings add gridy-header-menu element to gridy-grid container
<gridy-grid id="gridyGrid">
<gridy-header-menu></gridy-header-menu>
...
</gridy-grid>
To add context menu with settings add gridy-header-menu element to gridy-grid container
<gridy-toolbar id="gridyToolbar">
<gridy-toolbar-item>add</gridy-toolbar-item>
<gridy-toolbar-item>edit</gridy-toolbar-item>
<gridy-toolbar-item>delete</gridy-toolbar-item>
</gridy-toolbar>
toolbaritemclick - triggered when toolbar item is clicked, detail: item - dom obj of item is clicked, origEvent - mouse click event
Gridy grid components are emitting events that can help you to hook the process, e.g. you want to do some stuff after table header is rendered. All you have to do is to add event listener to particular event.
gridyTable.addEventListener('headrender', function(event) {
console.log('headrender', event, this);
});
List of events by elements:
gridy-table: headerRowRendered (deprecated) headrowrender headersRendered (deprecated) headrender bodyRowRendered (deprecated) bodyrowrender bodyRendered (deprecated) bodyrender rowclick (bubbles: true, composed: true) itemselect (bubbles: true, composed: true) itemdeselect (bubbles: true, composed: true)
gridy-view: itemselect (bubbles: true, composed: true) itemdeselect (bubbles: true, composed: true)
gridy-table-info: tableInfoRendered
gridy-pager: pageChanged (deprecated) pagechange pagerButtonRendered pagerRendered
gridy-filter: filterChanged (deprecated) filterchange gridy-per-page: perPageChanged (deprecated) perpagechange
You can place contents inside template tag with matching ids to make renderer overriding templates with by your versions. The highest priority is for lookup inside current html element, then document is searched and after that template path attribute is loaded.
So you can copy markup from theme inside tag, modify and component will use it. Here is the map of template attributes to loaded element ids below.
gridy-table: head-tpl-path -> tableHeadTpl body-tpl-path -> tableBodyTpl row-pane-tpl-path -> tableRowPaneTpl
gridy-table-info: tpl-path -> tableInfoTpl noent-tpl-path -> noEntriesInfoTpl (optional)
gridy-view: tpl-path -> GridyViewTpl : view.tpl.html
gridy-pager: body-tpl-path -> pagerBodyTpl item-active-tpl-path -> pagerActiveItemTpl item-tpl-path -> pagerItemTpl
gridy-filter: tpl-path -> pagerItemTpl
gridy-spinner: tpl-path -> spinnerTpl
gridy-per-page: tpl-path -> perPageTpl
all:
theme - theme name (default: 'default')
base-path - base path to files
config-sl - config tag selector
lang - lang code
tpl-vars - json with data for templates prerendering
gridy-grid:
impl-path - path to impl class
sort-field - sort field jsonpath
sort-direction - sort fied initial direction (default: 'asc')
config-tn - confiruation element tag name (default: 'gridy-config')
table-tn - table element tag name (default: 'gridy-table')
ds-tn - datasource element tag name (default: 'gridy-data-source')
df-tn - datafield element tag name (default: 'gridy-data-field')
filter-tn - filter element tag name (default: 'gridy-filter')
pager-tn - pager element tag name (default: 'gridy-pager')
info-tn - info element tag name (default: 'gridy-table-info')
spinner-tn - spinner element tag name (default: 'gridy-spinner')
per-page-tn - per-page element tag name (default: 'gridy-per-page')
per-page - number of elements per page (default: not set)
cur-page-num - current page number (default: not set)
selectable - user can select rows by click, options: 'multi', (default: not set -> no)
gridy-table:
impl-path - path to impl class
sort-direction
headers | show-headers - show field titles in heading (default: not set -> true)
show-footers - render table footer (default: not set -> false)
head-in-foot - render column names in footer just as in header
sort-field - sort field jsonpath
tpl-path - path to base template
head-tpl-path - path to head template
body-tpl-path - path to body template
foot-tpl-path - path to body template
row-pane-tpl-path - path to row pane template
ds-ref - datasource instance reference
pg-ref - pager instance reference
per-page - number of elements per page (default: not set)
cur-page-num - current page number (default: not set)
selectable - user can select rows by click, options: 'multi', (default: not set -> no)
table-tn - table tag name (default: 'table')
head-tn - table header tag name (default: 'thead')
foot-tn - table footer tag name (default: 'tfoot')
hcell-tn - table footer tag name (default: 'th')
row-tn - table footer tag name (default: 'tr')
cell-tn - table footer tag name (default: 'td')
gridy-view: impl-path - path to impl class tpl-path - path to base template ds-ref - datasource instance reference pg-ref - pager instance reference dri - driver code selectable - user can select rows by click, options: 'multi', (default: not set -> no)
gridy-table-info:
impl-path - path to impl class
tpl-path - path to base template
noent-tpl-path - no entries message template path
lang-path - language relative path
lang-full-path - language full path
per-page - number of elements per page (default: not set)
gridy-pager:
impl-path - path to impl class
body-tpl-path - body template path
item-tpl-path - item template path
item-active-tpl-path - active item template path
per-page - number of results per page
cur-page-num - current page number
total-results - total results number
total-pages - total pages number
ds-ref - datasource instance reference
gridy-filter:
impl-path - path to impl class
field-title - filter by particular field (selected by Title)
field-label - overrides label for field
filter-mode - filter mode, "gt" - keep greater values, "ge" - keep greater or equal values,
"lt" keep smaler values, "le" - keep smaler or equal values,
"cntn" - keep by substring containity, "eq" - keep equals, "ne" - keep not equal values
default: unset -> keep by substring containity
gridy-spinner:
impl-path - path to impl class
gridy-per-page:
impl-path - path to impl class
per-page - number or rows for one page (default: 10)
per-page-options - number or rows for one page (default: 10, 25, 50, 100)
per-page-default - override default per page number (default: not set -> 10)
http/2+ allows to do request multiplexing that means a lot of smaller requests to the same host are better than big blocking requests to multiple hosts. But if you think you still need to load all in one bundle, you can use aggregated template bundles loaded with js or included to page by server.
<script>
const loadTemplates = async () => {
await fetch('node_modules/gridy-grid/dist/gridy-antd.tpls.native.html')
.then(response => response.text())
.then(text => document.body.insertAdjacentHTML('beforeend', text));
};
loadTemplates();
</script>
You can control template loading/caching behaviour either individually or with gridy-grid element attributes:
rd-cache - enables/disables templates caching and inline overriding (default: enabled)
rd-cache-global - if cached template wasn't found allows to lookup in document (default: enabled)
You can even enable rendering with Handlebars templating library for your overriden templates. To have this you must provide Handlebars static import.
<script src="./node_modules/handlebars/dist/handlebars.js"></script>
or any other way to set global Handlebars instance to window or inject renderer property (not attribute).
Also add option rd-var-render enabled for renderer instance passed to gridy-grid or gridy-table element as attribute. It can be 'handlebars' to load handlebars or loader window function name to call. If attribute is not defined, simplified built-in renderer that support only variables will be used.
There is an option to use handlebars templates format instead of Native Templates to support legacy browsers like Internet Explorer. It can be enabled with rd-tpl-fmt="handlebars" attribute to gridy-grid element. You will also need a kinda transpiler with modules, classes etc. support enabled to be able to see rendering results. In addition handlebars tpl format requires jquery library present in runtime.
Data is loaded from REST service, ant.design framework theming enabled. Paging and filtering components added;
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.19.8/antd.css">
<gridy-filter id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
<style>
th.sort.sort-desc::after {
content: '▼';
}
th.sort.sort-asc::after {
content: '▲';
}
</style>
<script type="module">
import { GridyTable } from '/node_modules/gridy-grid/src/table/gridy-table.js';
import { GridyPager } from '/node_modules/gridy-grid/src/pager/gridy-pager.js';
import { GridyFilter } from '/node_modules/gridy-grid/src/filter/gridy-filter.js';
import { DataSourceLocal } from '/node_modules/gridy-grid/src/datasource/data-source-local.js';
import { DataSourceAjax } from '/node_modules/gridy-grid/src/datasource/data-source-ajax.js';
//let dataSource = new DataSourceLocal();
let dataSource = new DataSourceAjax();
dataSource.fields = [
{ title: 'Title', path: '$.title' },
{ title: 'Price', path: '$.price' }
];
dataSource.url = 'http://127.0.0.1:8080/paged';
let filter = document.getElementById('gridyFilter');
filter.tplPath = '/node_modules/gridy-grid/src/theme/antd/filter.tpl.html';
filter.dataSource = dataSource;
let pager = document.getElementById('gridyPager');
pager.dataSource = dataSource;
pager.theme = 'antd';
pager.bodyTplPath = '/node_modules/gridy-grid/src/theme/antd/pager-body.tpl.html';
pager.itemTplPath = '/node_modules/gridy-grid/src/theme/antd/pager-item.tpl.html';
pager.itemActiveTplPath = '/node_modules/gridy-grid/src/theme/antd/pager-item-active.tpl.html';
let table = document.getElementById('gridyTable');
table.dataSource = dataSource;
table.pager = pager;
table.filter = filter;
table.headers = true;
table.theme = 'antd';
table.headTplPath = '/node_modules/gridy-grid/src/theme/antd/table-head.tpl.html';
table.bodyTplPath = '/node_modules/gridy-grid/src/theme/antd/table-body.tpl.html';
customElements.define('gridy-filter', GridyFilter);
customElements.define('gridy-table', GridyTable);
customElements.define('gridy-pager', GridyPager);
</script>
Gridy has chart component that uses datasources to initialize chart libraries.
e.g. for Chart.js install library
npm i chart.js gridy-chart-chartjs
and plug it to your page
<script src="/node_modules/chart.js/dist/chart.js"></script>
then add element to your container or setup it programmatically
<gridy-grid id="gridyGrid" base-path="/node_modules/gridy-grid/src" sort-field="$.title">
<gridy-data-source fields='[{ "title": "Price1", "path": "$.price1", "borderColor": "red", "backgroundColor": "green", "borderWidth": 1 },{ "title": "Price2", "path": "$.price2", "borderColor": "green", "backgroundColor": "yellow", "borderWidth": 1 }]'
datasource-type="DataSourceLocal" datapath="$.data"></gridy-data-source>
<gridy-chart dri="chart-js" type="line" width="400" height="300" options='{"scales":{"y":{ "beginAtZero": true }}'></gridy-chart>
</gridy-grid>
<script>
let data = [];
for (let i = 0; i < 10; i++) {
data.push({ price1: 200 * i, price2: 100 * i })
}
let grid = document.querySelector('#gridyGrid');
grid.addEventListener('bootstrap', () => {
//grid2.charts[0].dri = function() { return dri }; // you can override driver at runtime
grid.charts[0].addEventListener('skrender', (event) => {
grid.dataSource.loadData(data);
});
});
</script>
When each field is data provider for own chart set, chart dataset parameter can be passed as field props or attribues
<gridy-data-source
datasource-type="DataSourceLocal" datapath="$.data">
<gridy-data-field title="Price1" path="$.price1" border-color="red" background-color="green" border-width=1></gridy-data-field>
<gridy-data-field title="Price2" path="$.price2" border-color="blue" background-color="white" border-width=1></gridy-data-field>
</gridy-data-source>
To use without gryd-grid container you must specify at leas ds-ref attribue pointing to gridy-data-source element id or setup dataSource programmatically.
<gridy-data-source id="gridyDs" fields='[{ "title": "x", "path": "$.x" },{ "title": "y", "path": "$.y"},{ "title": "Group", "path": "$.group"},{ "title": "Color", "path": "$.color"}]'
datasource-type="DataSourceLocal" datapath="$.data"></gridy-data-source>
<gridy-chart id="gridyChart" ds-ref="gridyDs" type="line" tooltip dri="d3" field-color="Color" field-x="x" field-y="y" width="400" height="400"></cbr-chart>
<script type="module">
let data2 = [];
data2.push({ x: 100, y: 100, group: 'a', color: '#98abc5' });
data2.push({ x: 200, y: 150, group: 'a', color: '#98abc5' });
data2.push({ x: 300, y: 270, group: 'a', color: '#98abc5' });
data2.push({ x: 400, y: 350, group: 'b', color: '#98abc5' });
data2.push({ x: 500, y: 460, group: 'b', color: '#98abc5' });
data2.push({ x: 600, y: 770, group: 'b', color: '#98abc5' });
data2.push({ x: 700, y: 840, group: 'c', color: '#98abc5' });
data2.push({ x: 800, y: 990, group: 'c', color: '#98abc5' });
let chart = document.querySelector('#gridyChart');
let ds = document.querySelector('#gridyDs');
customElements.define('gridy-data-source', GridyDataSource);
customElements.define('gridy-chart', GridyChart);
chart.whenRendered(() => {
chart.dataSource.loadData(data2);
});
</script>
ds-ref - to specify DataSource element id/global name
pg-ref - to link table to pager
share-chart-dri - share chart driver instance from cache than instancinate, ok when all types of chart on page have the same type
Supported Drivers:
Gridy has gridy-view that allows extensible and templatable components to display from datasource.
E.g. you can install gridy-view-icongrid package and use it transparently.
<gridy-grid id="gridyGrid2" base-path="/node_modules/gridy-grid/src" sort-field="$.title">
<gridy-data-source fields='[{ "title": "Name", "path": "$.name" },{ "title": "Value", "path": "$.value"},{ "title": "Group", "path": "$.group"}]'
datasource-type="DataSourceLocal" datapath="$.data"></gridy-data-source>
<gridy-view
dri="icongrid" id="gridyChart2" field-name="Name" field-value="Value" width="400" height="400"></gridy-view>
<gridy-pager id="gridyPager2"></gridy-pager>
</gridy-grid>
dri - driver code
field-{name}={title} - field mappings from data sources, valus will be mapped to rendering context by {name}
tpl-path - path for template to load
item-tpl-path - path for item template to load
item-tpl-str - template item with string value
tpl-vars - variables for prerendering templates
impl-path - path to theme based impl override
ds-ref - to specify DataSource element id/global name
pg-ref - to link table to pager
selectable - enables ability to select items, selection can be taken from props selectedItems, selectedItem, prevSelectedItem, possible values: multi or any/empty means single, default (empty -> single selection)
selection-emit - choses how selection will be emited, e.g. on long click/tap or click, possible values: "tap" - select by long click/tap, "click", "ctrl+click", "shift+click", "alt+click" (default: no -> click)
time-to-select - time to select for tap mode in miliseconds, (default: 700x)
share-dri - share chart driver instance from cache than instancinate, ok when all types of chart on page have the same type
Supported Drivers:
gridy-grid element supports lang attribued that allows developer to provide elements translated by locale resources. Resources for translation are shipped with themes.
<gridy-grid theme="antd" id="gridyGrid" lang="ru_RU">
<gridy-filter id="gridyFilter"></gridy-filter>
<gridy-table id="gridyTable"></gridy-table>
<gridy-pager id="gridyPager"></gridy-pager>
</gridy-grid>
You can use plugins as derived from SkElement, with possibility to load from element attributes configuration as follows
<gridy-chart id="gridyChart2" title="Foobar" legend='{"data": ["sales", "markt"], "orient": "vertical", "right": 10, "top": "center"}'
options='{"xAxis": { "data": "names" }, "yAxis": {}}'
type="multi:bar:sales,line:markt" dri="echarts" echarts-renderer="svg"
attr-plugins="true" plg-foo-cn="MyPlugin" plg-foo-path="/my-plugin.js"
value-field field-name="Name" field-value="Value" field-group="Group" inner-radius="50" width="400" height="400"></gridy-chart>
To have browsers up to IE11 supported you definitely need to load WebComponents polyfills.
Rendering engine must be changed to handlebars.
Also jquery needs to be loaded before bundle as it is used to generate table markup.
Initializing code must be wrapped into WebComponentsReady hook event.
In the example below polyfills from skinny-widgets library are used. You should install it or plug your own.
npm i skinny-widgets --save
<script src="/node_modules/skinny-widgets/compat/dialog-polyfill.js"></script>
<script src="/node_modules/skinny-widgets/compat/fetch.umd.js"></script>
<script src="/node_modules/skinny-widgets/compat/polyfill.min.js"></script>
<script src="/node_modules/skinny-widgets/compat/webcomponents-lite.js"></script>
<script src="/node_modules/skinny-widgets/compat/custom-elements-es5-adapter.js"></script>
<script src="/node_modules/skinny-widgets/compat/event-target.js"></script>
<link rel="stylesheet" type="text/css" href="/node_modules/gridy-grid/antd.min.css">
<sk-config
theme="antd"
base-path="/node_modules/gridy-grid/src"
lang="ru"
id="gridConfig"
></sk-config>
<gridy-table config-sl="#gridConfig" id="grid" pgref="pager" rd-tpl-fmt="handlebars"></gridy-table>
<gridy-pager config-sl="#gridConfig" id="pager" dsref="dataSource"></gridy-pager>
<script src="/node_modules/skinny-widgets/dist/skinny-widgets-bundle.js"></script>
<script src="/node_modules/jquery/dist/jquery.js"></script>
<script src="/node_modules/gridy-grid/dist/gridy-grid-bundle.js"></script>
<script>
window.addEventListener('WebComponentsReady', function(e) {
var dataSource = new DataSourceLocal();
dataSource.fields = [
{ title: 'Title', path: '$.title' },
{ title: 'Price', path: '$.price' }
];
var data = [];
for (let i = 0; i < 25; i++) {
data.push({ title: 'row' + i, price: 100 * i })
}
grid.dataSource = dataSource;
customElements.define('sk-config', SkConfig);
customElements.define('gridy-pager', GridyPager);
customElements.define('gridy-table', GridyTableAntd4);
dataSource.loadData(data);
});
</script>
You can run sample data backend and index.html serving from this project's root.
npm run server
Gridy Grid currently has only one external runtime dependency that is actually source bundled to avoid problems in untranspilled environments. So in case you want to use that library (complets) from it's own npm package or somewhere else e.g. shared bundle you may use SystemJS loader map to resolve Gridy's internal dependencies.
First add and setup module loader for your project.
npm i systemjs systemjs-transform-babel --save
And do configuration that will transpile and resolve the code.
<script src="/node_modules/systemjs/dist/system.js"></script>
<script src="/node_modules/systemjs/dist/extras/transform.js"></script>
<script src="/node_modules/systemjs-transform-babel/dist/babel-transform.js"></script>
<script type="systemjs-importmap">
{
"imports": {
"gridy-grid": "./node_modules/gridy-grid/src/gridy-grid.js",
"data-source-local": "./node_modules/gridy-grid/src/datasource/data-source-local.js",
"/node_modules/gridy-grid/complets/": "/node_modules/complets/"
}
}
</script>
<script>
Promise.all([System.import('gridy-grid'), System.import('data-source-local')]).then((m) => {
let dataSource = new m[1].DataSourceLocal();
//let dataSource = new DataSourceAjax();
dataSource.fields = [
{ title: 'Title', path: '$.title' },
{ title: 'Price', path: '$.price' }
];
let grid = document.querySelector('#gridyGrid');
grid.dataSource = dataSource;
customElements.define('gridy-grid', m[0].GridyGrid);
// generate sample data for DataSourceLocal
let data = [];
for (let i = 0; i < 25; i++) {
data.push({ title: 'row' + i, price: 100 * i })
}
dataSource.loadData(data);
});
</script>
git submodule update --remote --merge
open test/tests.html from browser with statically served project root
or install webcomponents test runner
sudo npm install --global web-component-tester --unsafe-perm
and run with
wct --npm
FAQs
gridy grid datagrid web components library
The npm package gridy-grid receives a total of 8 weekly downloads. As such, gridy-grid popularity was classified as not popular.
We found that gridy-grid demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.