The datagrid component
- Introduction
- Example
- Properties
- Methods
- Events
- Customising the datagrid with CSS
- Integrating the datagrid with forms
- Frequently asked questions
Introduction
The datagrid
component is new to RGraph in
version 6.21
and is a very easy way to show
data to your users. It's very customisable with standard
css
and extensible with a whole host of
events and api
calls that are available. It can
be quickly integrated into your pages and forms so it
allows you to quickly and easily build your
website and standardise the look of data tables across
all of your pages.
Example
Here's a basic example of the datagrid
with resizable
columns which can be sorted by clicking on the
column headers. There's a button underneath the datagrid
which resets the column widths back to the default by
using an api
call.
<script src="RGraph.common.core.js" ></script> <script src="RGraph.common.datagrid.js" ></script> <script> data = [ ['Richard','Monday', 124], ['Jane', 'Tuesday', 152], ['Lucy', 'Wednesday', 98], ['Jerry', 'Thursday',95], ['Alex', 'Friday', 103], ['Freddy','Saturday', 111], ['Peter', 'Sunday', 56], ]; myGrid = new RGraph.Datagrid({ id: 'myGrid', data: data, options: { columnsHeaders: ['Name','Day of week','Amount'], columnsResizable: true, columnsResizablePersistent: true, columnsUnitsPre: ['','','<b>£'], columnsUnitsPost: ['','','</b>'], columnsHTML:[,,true] } }).draw(); </script>
Properties
You can use these properties to control how the
datagrid
appears. You can set them by including them in
the options section of the configuration as shown above.
- Column properties
- Sorting properties
- Editable properties
- Selectable rows properties
- Miscellaneous properties
Column properties
array
of strings
that are used as the headers to the columns. By default, these are bolded but you can change that by overriding the css
that the datagrid
specifies with your own. The headers are standard th
tags instead of td
tags and are nested inside a thead
tag instead of the tbody
tag.array
of strings
that are used as the footers. The footers are standard td
tags and are nested inside a tfoot
tag instead of the tbody
tag.array
. For example, if your first column is just an ID number or a checkbox/radio button then you may want this column to be smaller than the rest.html
is not interpreted by the datagrid
and is shown as-is to the user. You can change this behaviour though by specifying the column index in this option. It can either be a single number - the index of the field (the numbering starts at zero remember) or it can be an array
of numbers denoting the column indexes that you want to allow html
in.html
in this column it could be an opening tag (eg <b>
).html
in this column it could be a closing tag (eg </b>
).css
class to the columns (either the th
or td
tags) you can do so with this property. It can either be a string
- in which case it's added to all of the columns - or it can be an array
- in which case it's added to the td
tag which has the corresponding column index.string
that's used as the decimal point. It can be one or more characters.string
that's used as the thousand separator. It can be one or more characters.object
that contains both the number and meta information. It should return the relevant string
to show to the user. This can be both a single function that handles the formatting of all of the columns or it can be an array
of different functions - one per column. It can look like this:columnsFormatter: function (opt) { console.log(opt); return opt.number; },Or like this:
var f1 = function (opt) { // This is the formatter function for the THIRD column console.log(opt); return opt.number; } var f2 = function (opt) { // This is the formatter function for the SIXTH column console.log(opt); return opt.number; } //... columnsFormatter: [,,f1,,,f2]
true
. When enabled, there are resize handles between the header cells that you can grab to drag the columns left or right. If there are no column headers then your datagrid
columns will not be resizable.true
. The sizing information is stored inside the browser in the window.localStorage
variable.array
of truthy
or falsy
values. If the relevant value is falsy
then no resize handle is shown. For example, if your first column is checkboxes, radio buttons or an ID number for that row then you might not want the first resize handle to be shown.Sorting properties
array
of column indexes (the indexing begins at zero) that dictate whether a column is sortable or not. So for example, if your first column is a checkbox that you don't want to be sortable you can specify something like this: [1,2,3,4,5,6]
datagrid
. This property overrides any column index that's stored in your browser's localStorage
so if you change the ordering and refresh the page the sorting will revert to what's specified with this property.array
of functions - one per column. If you use an array
you can leave an entry blank or null
in the array
so that the default sorting is used for that column.// An example of a custom sort function which sorts // the rows by the last character in the cell. // Because an array encapsulates the function - // this function will only be used for the first // column. Normal sorting is used for the other // columns. // // @param object obj The chart object // @param number column A number representing the column index // (starts at zero). // @param number direction The direction to be sorted in. 1 // means ascending and -1 means // descending. // @param mixed a The first value to compare. // @param mixed b The second value to compare. // sortableCompare: [function (obj, column, direction, a, b) { a = a.substr(-1).charCodeAt(0); b = b.substr(-1).charCodeAt(0); return direction > 0 ? a - b : b - a; }]
Editable properties
datagrid
is editable or not. To edit a cell you can double-click on it. You can use the various datagrid events to perform an action when editing is either cancelled or completed (eg send that value back to the server with ajax
). For example:.on('editcomplete', function (obj) { var meta = RGraph.Registry.get('cell-edit-meta'); var data = obj.getData(); console.log(data[meta.row]); });
array
of column indexes that are allowed to be edited - for example: [1,6]
This would allow the second and seventh columns to be edited (remember that the indexing begins at zero). It can also be a string
of column indexes that can be editable (remember the indexing starts at zero) - some examples: 1-3
- The columns 1, 2 and 3 are editable.1-
- The columns with an index of 1 or higher are editable.-3
- The columns with an index of 3 or lower are editable.3
- The column with the index 3 is editable.1,2,3
- The columns with indexes 1, 2 or 3 are editable.0,1-3,4,5-6
- The columns with the indexes 1, 2, 3, 4, 5 or 6 are editable.
Selectable rows properties
true
. By making use of the rowsSelectable*
properties you can easily incorporate the datagrid
into a dynamic application. You'll most likely want to specify the property below as well.ids
to the data. The order of the ids
should correspond with the order of the data that you give to the datagrid
. There are demos of this property in the download archive. In order for the selected rows to be persistent you must give this property.Miscellaneous properties
css
styles to your datagrid
such as this:style: [ 'th:nth-child(2) {font-weight: bold; color: red;background-color: #ddd;}', 'td:nth-child(2) {font-weight: bold; color: red;background-color: #ddd;}' ]This property can either be a single
string
or an array
of strings
. As is shown in the example above, this doesn't have to be the full css
selector - it will be modified with the id
that you give to the constructor to limit the possibility of clashes. So the example above would be converted to look like this (assume that #myGrid
is the id
of your div
tag):style: [ 'div#myGrid table.rgraph-datagrid th:nth-child(2) {font-weight: bold; color: red;background-color: #ddd;}', 'div#myGrid table.rgraph-datagrid td:nth-child(2) {font-weight: bold; color: red;background-color: #ddd;}' ]
aria
description to the datagrid
. This aids people using assistive technologies - such as screen readers - to make more sense of the datagrid
.caption
property adds a standard caption
tag to the datagrid
. The caption
can be styled with css
and can be used in place of a title. The caption
can sometimes be skipped by screen readers though so you may prefer to use a regular heading tag instead. (eg a standard h2
tag)true
to add a filter box to the top left of the datagrid
. The filter is quite straightforward - just type into the text input and the rows that are displayed will be narrowed down to those that contain that text. The search is done in a case-insensitive manner and there's no regular expression search or boolean logic support.Methods
You can use these functions to do various things allowing
you to control and manipulate the datagrid
.
datagrid
. The raw data in the object
is an array
of objects
that holds meta information as well as the data - so if you want to get the raw data you should use this method.null
is returned.null
is returned.object
if you need to. This method takes the data and sets up the data structure that the datagrid
code requires. Because of that, this method should be used to set the data instead of setting the data
property directly. The return value is the data that you give the function.obj.data
property won't necessarily be in the original, unsorted order. So if that's what you want you can use this method to get the original, unsorted data.datagrid
. It does exactly as the name implies and returns you the original, unsorted index of the index that you give it.resetdata
event.datagrid
. It gets appended onto the original, unsorted data and then the data is sorted again using the current sort settings. For this reason, a row that you append may not be added at the end of the datagrid
. After doing this it fires the append
event.append
method, this method adds the data to the start of the dataset. Again, your current sort settings are taken into account so your new data may not appear at the start of the dataset. When the function is finished the prepend
event is fired.index
argument). The new data should have the same number of items/columns as the existing data. The index
argument is zero-indexed and can also be negative. In that case the counting starts at the end of the dataset and works backwards. When finished the method fires the insert
event.delete
event is fired.find
function searches through the data for the search query that you give it. You can either give the function a string
in which case the cell value has to match exactly or you can give it a Regular Expression which affords you a lot of flexibility in the search. Normally this function stops when it has found the first instance of the search query and returns but you can change this behaviour by passing an object
as the second argument which has an all
property set to true
. Some examples: obj.find('Jerry'); // Find the first instance of the word Jerry obj.find('Jerry', {all: true}); // Find all instances of the word Jerry obj.find(/^jer/i); // Regular expression find obj.find(/^jer/i, {all: true}); // Use a Regular expression and find all of the matchesBy default, the return value is an
object
containing the row index (the row
property), the column index (the column
property) and the html
table cell object
(the element
property). If you use the second argument to the function though to stipulate that all occurences of the search query should be found then the return value is an array
with one element per match. Each element is an object
with the same properties as the object
returned when performing a single search.find
function but with the difference that it returns all of the rows that contain the search query - not just the first one that it finds. You can use the find
function for this or the findAll
function - your choice. obj.find('Jerry', {all: true}); // These two functions are the same obj.findAll('Jerry'); // These two functions are the same
datagrid
from the document. It uses the modern and quick replaceChildren
dom
function to do this. It fires two events: the beforeclear
at the start of the function before anything has been done and then the clear
event after the container has been cleared of the datagrid
.datagrid
from the container div
and then redraws it. It fires two events: the beforeredraw
at the beginning of the call and the redraw
event after the datagrid
has been redrawn.jquery
on
function. The first argument is the event that you want to attach to and the second is the handler function. For example: .on('draw', function (obj) { // Put your code here. Depending on the event, you can sometimes // get meta information from the RGraph registry. See the list // of event types below for more detail. });
object
with two properties - row
and column
.rgraph-datagrid-row-selected
css
class. By default, this turns the background color blue and the color white - like Windows does when selecting icons (for example). This method is only useful when the rowsSelectable
property is enabled.rowsSelectable
property is enabled.array
of objects
that represent the current state of the selected items. It returns to you an array
of objects
and each object
has two properties - the current index in the datagrid
(this can change when the datagrid
is sorted) and the user-supplied id
which can be given with the rowsSelectableIds
property. This method is only useful when the rowsSelectable
property is enabled.true
or false
value as to whether the row with the given index is currently selected or not. This method is only useful when the rowsSelectable
property is enabled.rgraph-datagrid-row-selected
css
class from the row in order to remove the blue/white selection coloring. This method is only useful when the rowsSelectable
property is enabled.Events
These events are available to enable you to
integrate your own code with the datagrid
. You can use
the on
function to attach them to your
chart as is shown in the example below.
<script>
new RGraph.Datagrid({
id: 'myGrid',
ata: [
['15th March 2006', 'Jane', 19],
['8th August 2006', 'Freddy'],23,
['21st September 2006','Rod', 41],
['5th December 2006', 'Peter', 12],
['21st February 2007', 'Gary', 24],
['24th March 2007', 'Jamie', 37]
],
options: {
columnsHeaders: ['Date','Competitor','Score']
}
}).on('draw', function (obj) {
alert('Hello!');
}).draw();
</script>
draw
function runs - but only once. On subsequent draws, this event is not triggered.draw
event after you call the draw
function then this code will not run straight away - because the draw
function would have completed before you attach to the event.redraw
function - before the redraw has happened.redraw
function - after the datagrid
has been redrawn.clear
function - before the datagrid
has been cleared.clear
function - after the datagrid
has been cleared.resetData
function is called, which resets the data back to that which was initially given to the datagrid
.datagrid
data is sorted (by clicking on the headers to the columns).datagrid
data is sorted (by clicking on the headers to the columns).append
method which is used to add data to the end of the datagrid
.prepend
method which is used to add data to the start of the datagrid
.insert
method which is used to insert data into the datagrid
(at some point).delete
method which is used to remove data from the datagrid
.index
of the row and act accordingly..on('rowclick', function (obj) { var meta = RGraph.Registry.get('row-click-meta'); var object = meta.object; // The RGraph object var event = meta.event; // The standard event object var element = meta.element;// THe HTML element var html = meta.html; // The innerHTML of the row var row = meta.row; // The index of the row var value = meta.value; // All of the values of the row })
index
of the cell and act accordingly. .on('cellclick', function (obj) { var meta = RGraph.Registry.get('cell-click-meta'); var object = meta.object; // The RGraph object var event = meta.event; // The standard event object var element = meta.element;// THe HTML element var html = meta.html; // The innerHTML of the cell var row = meta.row; // The index of the row var column = meta.column; // The index of the column var value = meta.value; // The value of the cell })
.on('beforeedit', function (obj) { var meta = RGraph.Registry.get('cell-edit-meta'); var object = meta.object; // The RGraph object var value = meta.value; // The value of the cell var cell = meta.cell; // The HTMLcell var row = meta.row; // The index of the row var column = meta.column; // The index of the column }) Name: beforeeditsaveDescription:This event fires just before the cell that you've been editing is saved. There's meta information available to you and that is as follows:.on('beforeedit', function (obj) { var meta = RGraph.Registry.get('cell-edit-meta'); var object = meta.object; // The RGraph object var value = meta.value; // The value of the cell that's about to be saved var cell = meta.cell; // The HTMLcell var row = meta.row; // The index of the row var column = meta.column; // The index of the column }) Name: aftereditsaveDescription:This event fires right after an edit to a cell that you've made has been saved. The meta information that's available to you is the same as thebeforeeditsave
event:.on('afteredit', function (obj) { var meta = RGraph.Registry.get('cell-edit-meta'); var object = meta.object; // The RGraph object var value = meta.value; // The value of the cell that's about to be saved var cell = meta.cell; // The HTMLcell var row = meta.row; // The index of the row var column = meta.column; // The index of the column }) Note that if you want the before and after values of the cell you can use this event and the beforeedit
event.Name: editcompleteDescription:This event is fired when the edit is complete. It's much the same as theaftereditsave
event.Name: editcancelledDescription:This event is fired when the edit is cancelled by pressing theEsc
key. The same meta information as thebeforeeditsave
andaftereditsave
events is available..on('editcancelled', function (obj) { var meta = RGraph.Registry.get('cell-edit-meta'); var object = meta.object; // The RGraph object var value = meta.value; // The value of the cell that's about to be saved var cell = meta.cell; // The HTMLcell var row = meta.row; // The index of the row var column = meta.column; // The index of the column }) Name: resizebeginDescription:When resizable columns are enabled using thecolumnsResizable
property this event fires when resizing begins. This is when you initially click on the column resize handle in the columns header bar. Obviously, if you don't have thecolumnsHeaders
property in your config then you won't see the resize handles and thus won't be able to resize the columns.Name: resizeDescription:This event fires every time the columns are resized. In practice, this means that once you've clicked on the resize handle theresizebegin
event fires and also when you move your mouse left or right to resize the column.Name: resizeendDescription:This event will fire when you release the mouse button after you've finished resizing a column. Much like themouseup
event.Customising the datagrid with CSS
At its most basic level, the
datagrid
is anhtml
table
utilising standardtags. You can see the structure in the FAQ question below. This means that you can use standard
css
selectors to change the way that things look to the user. For example:<style> /* * Remember that you may need to use the !important modifier * if you're overriding the default styles. */ div#myGrid table.rgraph-datagrid tr.rgraph-datagrid-row-hover { background-color: #00f1 !important; } /* * If you have multiple datagrids on a page then you can also do * this to provide the row highlighting for all of them in one * go. */ .rgraph-datagrid-row-hover { background-color: #00f1 !important; } </style>Or if you want to highlight a particular row you can make use of the
css
nth-child
pseudo-selector like this:<style> /* Highlight the third row (in CSS the counting begins at 1) */ div#myGrid table.rgraph-datagrid tr:nth-child(3) { background-color: yellow !important; } </style>
Using the style property to set CSS
As well as setting your
css
the normal way - usingstyle
html
tags - you can also use thestyle
property of thedatagrid
. Here's an example:style: [ 'tr:nth-child(2) td:nth-child(2):hover {color: red; font-weight: bold;}', // ... ],
You shouldn't worry too much about naming clashes though because, if not present, the rule is made more specific by adding the
id
of thediv
tag to it. So the above rule is actually transformed into the following:style: [ 'div#myGrid table.rgraph-datagrid tr:nth-child(2) td:nth-child(2):hover {color: red; font-weight: bold;}', // ... ],Integrating the datagrid with forms
Integrating the
datagrid
with a form on your webpage can make it very useful when presenting the user with a choice and getting an answer from them. Consider the following example:This is the
html
code for thisdatagrid
. Notice that it sits within aform
tag and there's a submit button just below where thedatagrid
will be rendered.<form action="datagrid.html" method="post"> <div style="margin-left: auto; margin-right: auto; width: 600px"> <div style="width: 600px" id="myGrid"></div> <input type="submit" name="submit" value="Update" style="font-size: 20pt; cursor: pointer"/> </div> </form>And here's the code for the
datagrid
. Notice that thecolumnsHTML
option has been given and is set to anarray
that contains just one number -0
This means that the first column (the numbering begins at zero) is allowed to havehtml
in it. So a checkbox will be shown and not thehtml
tag for the checkbox.<script> data = [ ['<input type="checkbox" name="players[]" value="15" style="transform: scale(1.5)" />', 'Mary','1st October 1985','Winner by default'], ['<input type="checkbox" name="players[]" value="2" style="transform: scale(1.5)" />', 'Freddy','27th July 1980','3rd place - runner up'], ['<input type="checkbox" name="players[]" value="43" style="transform: scale(1.5)" />', 'Jamie','6th March 1967','2nd place - finalist'], ['<input type="checkbox" name="players[]" value="21" style="transform: scale(1.5)" />', 'Gary','7th April 1982','1st place - winner'], ]; myGrid = new RGraph.Datagrid({ id: 'myGrid', data: data, options: { columnsHeaders: ['', 'Person','Date of event','Final position'], columnsHTML: [0], columnsWidths: [30], sortable: false } }).draw(); ///////////////////////////////////////////////////////////// // The following code is OPTIONAL - it allows you to click // // the entire row to select and unselect the checkbox as // // well as the checkbox itself. // ///////////////////////////////////////////////////////////// //(function () //{ // // // // Get all of the rows in the datagrid and add click event // // listeners that check the checkbox in that row. // // // var els = document.querySelectorAll('div#myGrid1 table tbody tr'); // // for (var i=0; i<els.length; ++i) { // // els[i].addEventListener('click', function (e) // { // var tr = e.currentTarget; // var input = tr.querySelector('input[type=checkbox]'); // // input.checked = !input.checked; // }, false); // // // // // If the checkbox is clicked on directly - cancel any // // propagation up the event tree. // // // var el = els[i].querySelector('input[type=checkbox]'); // // el.addEventListener('click', function (e) // { // e.stopPropagation(); // }, false); // } //})(); </script>But what if you didn't want the first column to have the same styling as the rest of the table? Well, you could do that with a snippet of
css
, utilising thenth-child
pseudo-selector and moving the submit button to the right a small amount accordingly - so that it lines up with, what is now, the main table. Here's the updated example along with the necessarycss
code:The necessary
css
markup:<style> div#myGrid-container input[type=submit]{ margin-left: 30px; } div#myGrid input[type=checkbox] { cursor: pointer; } div#myGrid th:nth-child(1n+2) { background-color: black !important; color: white !important; } div#myGrid thead th:nth-child(1), div#myGrid tbody td:nth-child(1) { background-color: white !important; } div#myGrid thead th:nth-child(1) div, div#myGrid tbody td:nth-child(1) div { border: none !important; } </style>The
html
markup and thejavascript
code is the same as the example above - so you can use that.Adding a "select all" button to your datagrid
If you're adding checkboxes to your
datagrid
then one thing that you may want is an easy way for your users to check all of those checkboxes at once. This is quite easy and just requires a littlejavascript
function like this:<script> // // A function that facilitates the easy selection of all of // the checkboxes on the datagrid in one go. // function selectAll () { var checkboxes = document.querySelectorAll('div#myGrid input[type=checkbox]'); checkboxes.forEach((value,key,array) => { value.checked = !window.allCheckboxesCheckedState; }); window.allCheckboxesCheckedState = !window.allCheckboxesCheckedState; } </script> <button onclick="selectAll()">Select all</button>Frequently asked questions
- What is the structure of the resulting table?
- How do I make the rows highlighted when they're hovered over?
- How can I add scrolling to my datagrid?
- How do I hide my ID column?
- How do I make my checkboxes toggle when the row is clicked?
What is the structure of the resulting table?
The RGraph
datagrid
produces a standardhtml
table
element with the following structure:<div id="myGrid"> <table class="rgraph-datagrid"> <!-- Column headers --> <thead> <tr> <th><div class="rgraph-datagrid-cell-content">Name</div></th> <th><div class="rgraph-datagrid-cell-content">Day</div></th> <th><div class="rgraph-datagrid-cell-content">Amount</div></th> </tr> </thead> <!-- Data rows --> <tbody> <!-- First row --> <tr> <td><div class="rgraph-datagrid-cell-content">Richard</div></td> <td><div class="rgraph-datagrid-cell-content">Monday</div></td> <td><div class="rgraph-datagrid-cell-content">23</div></td> </tr> <!-- Second row --> <tr> <td><div class="rgraph-datagrid-cell-content">David</div></td> <td><div class="rgraph-datagrid-cell-content">Tuesday</div></td> <td><div class="rgraph-datagrid-cell-content">46</div></td> </tr> </tbody> <!-- Column footers --> <tfoot> <tr> <td><div class="rgraph-datagrid-cell-content"></div></td> <td><div class="rgraph-datagrid-cell-content"></div></td> <td><div class="rgraph-datagrid-cell-content"></div></td> </tr> </tfoot> </table> </div>How do I make the rows highlighted when they're hovered over?
You can do this by adding a small bit of
css
to your page. To be specific to a singledatagrid
you could add this:<style> /* Add row highlighting to a single datagrid */ div#myGrid table.rgraph-datagrid tr.rgraph-datagrid-row-hover { background-color: #00f1 !important; } </style>
Or to add row highlighting to all of the
datagrid
instances on the page you can use acss
: selector that's a broader match like this:<style> /* Add row highlighting to all of the datagrids on the page */ .rgraph-datagrid-row-hover { background-color: #00f1 !important; } </style>
How can I add scrolling to my datagrid?
If you have a lot of data that you want to show in the
datagrid
but don't want it to take up a large amount of vertical space then there is something that you can do and that's to add scrolling to thedatagrid
body. This is demonstrated by thedatagrid
that's shown above and you can also see a demo in the download archive. It's done by adding a small amount ofcss
to your page and that is as follows:<style> div#myGrid table.rgraph-datagrid { display: block; } div#myGrid table.rgraph-datagrid tbody { max-height: 150px; overflow-x:hidden; overflow-y:auto; display: block; width: 100%; } </style>How do I hide the ID column on my grid?
What if you have a set of data and the first column is an
id
that perhaps is coming from your database? Maybe it's just not practical to not select that column in the first place but you don't want that information displayed to the user. Well instead of messing with the data you can just hide that column with a littlecss
. Here's thedatagrid
before thecss
has been applied with theid
column still visible.And here's the
css
that hides the first column. It also centers thedatagrid
in its container (there's a tiny bit of space left on either side and this is because of the now missing column).<style> div#myGrid table { margin-left: auto; margin-right: auto; } div#myGrid table.rgraph-datagrid tr :where(th, td):nth-child(1) { display: none; } </style>And here's the resulting
datagrid
which has now got the first column hidden.<script> myGrid6 = new RGraph.Datagrid({ id: 'myGrid6', data: [ [435, 'Richard','Web developer',25000], [884, 'Jane', 'Customer Service Operative',18000], [463,'Martha','Sales executive',23000], [135,'Janet','Office admin',21000] ], options: { columnsHeaders: ['','Name','Occupation','Salary'], // Reduce the size of the first column columnsWidths: [5], style: [ // Center the datagrid in its div 'table {margin-left: auto;margin-right: auto;}', // Hide the first column (which has the ID numbers in) 'tr :where(td, th):nth-child(1) {display: none;}' 'tr th div {background-color: black; color: white;}', 'tr th span {color: white;}' ] } }).draw(); </script>How do I make my checkboxes toggle when the row is clicked?
The datagrid example that's shown above shows you how to do this and has an example of the necessary code beneath the
datagrid
. The commented-out code (in green) is thejavascript
that's necessary to add to your page.