JSON Grid Private
About this demo
- Most columns read their template from an .html file next to the page, found like a panel's markup: IdColumn.html, FirstNameColumn.html, LastNameColumn.html, AddressColumn.html and PhonesColumn.html. Switching to German picks the _de or _es variants where they exist, and the headers come from the page's properties
- "Push the rows" sends the rows of the current page, in reverse order, as JSON over the web socket connection, and the table repaints them in the browser without any request to the server. The server always serves the rows sorted by first name, so the reversed order can only have come from the push; a refresh restores it
- The edit, delete and download buttons are IconBasedRowActions: plain markup, not components, with their tooltip as title. A click goes to the table, which looks the row up by its key and hands it to the action registered for the button
- The pencil opens a form in the Modal of ui-components, the dialog the React and Svelte tabs use too: a title, the form and a × that closes it, over the dimmed page; drag the title to move the dialog, double-click it to fold it. Escape closes it too, and once a field was changed it asks first whether to discard the changes. Every field is required; the address column shows the street, city and country in one line, the form edits them separately. Saving updates the user and repaints the rows
- The bin asks to confirm the deletion in the same dialog before it deletes the user
- While a request of the table runs, for example saving, deleting or paging, a veil blocks the table and, if it takes a while, shows a spinner in the theme's colors. The hourglass in the navigation runs a slow action, which takes two seconds on the server, to show it
- The body of the table is 800 pixels high and scrolls, while the headers, the toolbars above them and the navigation below stay in view; a page with fewer rows leaves the rest empty, so the table keeps its height. "Body height" and its unit above change it: pixels, percent of the window's height, or percent of the parent's height, which needs a parent with a height of its own and is as high as the rows here; a negative height lets the body take the height of its rows
- Double-click a phone number to copy it to the clipboard: a ClipboardCopyBehavior script copies it and shows a check mark on it. Whatever is typed into the form, such as markup or script in a name, is shown as text everywhere
- The download button saves the user as a jCard (RFC 7095), the JSON form of the vCard format address books exchange users in, through an AjaxDownloadActionColumnContributor shown as an icon: the browser fetches the file itself and hands it to its own download manager. Each row's element carries an id made of the table's id and the row key, so a row keeps its identity whatever happens to the rows around it
- The Progress column is a ProgressBarColumn, whose cells are the markup of the ProgressBar component, striped and moving. While the page is open, a timer of its own advances the progress of random users among those the page shows every 100 ms, and pushes the changed rows over the web socket connection every 3 seconds; each push repaints only its row. The table reports the rows it sends to the browser, so rows on other pages are neither advanced nor pushed. Clicks keep working while the rows repaint, because they are dispatched by the row key
- The first, last name and born columns sort the rows when their header is clicked, the highlighted arrow showing the order. Sorting queries the users again on the server, shows the first page, repaints every row and clears the selection; the # column numbers the rows across pages, and the navigation is shown above and below the table
- Columns can be resized by dragging the right edge of a header, or with the arrow keys on that edge, never narrower than 80 pixels. While dragging, a line with arrows shows where the edge will land, a shaded band the new extent of the column and a label its width in pixels. The columns are resizable because the page added a ResizableColumnsBehavior to the table, and the table grows with them; the "Resizable" option above adds or removes it. The selection, #, Actions and ID columns cannot be resized. Each resize is sent to the server, which renders the table with the same widths next time
- The table takes the full width of the page, sharing it among the columns by their content; "Width" switches to a table as wide as its columns. "Proportions" lets the page set the relative widths of the columns instead. While no column has been resized, a full-width table follows the size of the window
- The (i) next to every setting above says what it does; every change is posted via Ajax. The same settings and actions, with the rows rendered on the server, are in the BeanBasedDynamicDataTable example
- The options above also place the navigation and the selection bar on top, at the bottom or both, and choose the theme: the colors of the table, its progress bars and this explanation come from a theme of ui-components, switched by a CSS class only. The rows per page are chosen in the navigation, with the same Dropdown as the settings
- The database of this example holds a thousand users. The text field in front of the navigation filters them by first and last name as you type; it is a component the example plugs into the navigation, not a feature of the table
- "Rows from" chooses where the browser fetches the rows from: an Ajax behavior of the table on this page, or a JsonRowsResource mounted at /api/users, a stateless request that does not touch the page, with the page, the sort and the filter in its URL. Paging, sorting and selecting still go through the page
- The download button after the paging links exports the selected users as a CSV file, or all of them if none is selected, through a CsvExportToolbarAction
- The checkboxes of the first column select rows; the selection is kept on the server, by key, so it survives paging, sorting and pushes. The header checkbox selects the page and shows whether all, some or none of its rows are selected. Once the whole page is selected, a bar below the top navigation offers to select every user; checking or unchecking a row afterwards turns the selection back into the rows the page shows checked. The navigation tells how many users the server holds as selected, such as "2 selected": a SelectionCountToolbarAction added to the table, which "Selection count" above turns off and on. The checkboxes are drawn by the table in the colors of the theme, the same in every browser and visible on the color of the headers
- Editing a user also selects it and shows it in the details panel below the table
- Delete a user in one tab and click it in another: the click still reaches the table, which reports that the user is gone instead of failing with a missing component
- The plus in the navigation is an IconBasedToolbarAction: it opens the same form as the pencil, empty, and adds the user it is saved with
- "Icons" switches the icons of the actions between the built-in ones, SvgIcon, the solid icons of Font Awesome as inline SVG read from its web jar, which need no style sheet or font, and FontAwesomeIcon, the same icons drawn by the Font Awesome font, which the page loads from its web jar. Every icon is an IIcon
- The button with the columns in the navigation is a ColumnChooserToolbarAction: it lists the columns implementing IHideableColumn, those after ID, with a tick on those shown. Click a column to tick or untick it and apply to show the ticked ones; Home phone, Cell phone, City and Country are hidden at first
- The page added a MovableColumnsBehavior to the table, and the columns after ID implement IMovableColumn: drag the dotted handle in front of their title, with the mouse, a pen or a finger, and drop the column between two others, a line with arrows showing where it will land, or move it with the arrow keys on the handle. The selection, #, Actions and ID columns keep their places, so no marker is shown where the column would move one of them. After a move the table is rendered again with its rows, without fetching them
- The table remembers the order, the visibility and the widths of its columns in its column state store, the session by default: reload the page and the columns are as you left them. "Column state" switches to a store of this example keeping the states in a file of the temporary directory, which survives restarts of the server; an application would keep them in its database, by user, through an IColumnStateStore of its own. "Reset the columns" brings back the order, visibility and widths the page starts with
- "Infinite scroll" turns the pages into one list: whenever the body is scrolled to its last row, the table fetches the next page of users and adds them, blocked by its veil meanwhile. The paging links and the rows per page are left out and the navigation tells how many users are shown; sorting or filtering starts over from the first page. It is JsonBasedDynamicDataTable.setInfiniteScroll(true)
- The scroll bar of the body looks the same in every browser: the native one is hidden and a ScrollbarBehavior script draws a slim one in the theme's colors, which can be dragged or clicked; the wheel, the keys and touch scroll as usual
- The settings take the whole width of the page in as many columns as fit. "Reset the columns" and "Push the rows" are AjaxActionButtons, the buttons of the Buttons demo
The React and Svelte tabs hold an empty element of this page each, which an app of @antilia/react or @antilia/svelte renders the same grid into, with its DataTable: the framework renders the headers, the navigation and the column chooser, the script of the Wicket grid renders the rows from the same column templates. Columns move, resize and hide as here, rows are selected with the same checkboxes, counted in the navigation. The drop-downs on top choose where the rows come from: the mounted resource /api/users, which creates, changes and deletes them too (POST, PUT and DELETE), so what the app saves is what this page shows; or a local list of JSON, the first 200 users the page gave the app, which the DataTable filters, sorts and pages in the browser and the app changes in the browser only. They also choose paging or infinite scrolling, the selection, its count and resizable columns. The grid is private in the browser too: it checks the application's license key with the same signature and shows the same placeholder without one.