The DataTable is a control which allows you to add dynamic table to your forms.
You can set up how many columns the table has and their type, and the users will be able to add entries to this table.
Most configuration for DataTable can be done by editing individual column settings. To add a new column, simply click on the plus symbol:
Here you can find properties specifically related to the DataTable control.
The text that will appear above the control:
You can toggle Title’s visibility on/off:
Title can be changed directly on the form after a double click:
JavaScript
This code will allow you to get or set the controls’s title dynamically:
//returns the control's title as a string
fd.control('Control1').title
//sets the control's title
fd.control('Control1').title = 'Your order'
A unique identifier for the control.
Important
Do not change the control’s name after the form has been in use, or you might lose saved data or break your automation.
JavaScript
The Name property allows to work with the control via JavaScript code, like this:
fd.rendered(function(){
//can access the control using its Name,
fd.control('Control1').value = [{Product: 'White T-shirt', Amount: 3, ExpectedDate: new Date(), Delivered: false}];
});
Define whether the control will be required to submit the form or not:
Required status can also be changed directly on the form via the Asterisk button:
The property defines the width of the control in pixels.
If left blank, the control takes up the entire available width in the current grid cell.
Allows to select where the new line will be added — at the Top or at the Bottom of the table.
Here you can find properties specifically related to the DataTable columns.
A unique identifier for the column.
Important
Do not change a column’s name after the form has been in use, or you might lose saved data or break your automation.
Allows you to set the width of the column.
The column can still be dragged by the user on the form to manually resize it:
Allows to select the type of the data for the column — can be either String, Number, Boolean, Date or Dropdown.
Here you can find properties specifically related to the Number type columns.
Only available for the Number column type.
Specify the minimum and maximum values that a user can enter:
When a user enters a value outside the range, the value changes to the nearest valid value:
Only available for the Number column type.
Specify the number of decimal places to which the number will be rounded. The default property value is 0.
Only available for the Number column type.
Specify the number format that is applied when a user leaves the control. The default property value is n0.
The number format is made up of format specifier and the number of decimals places. E.g. n3, c2.
Avaliable format specifiers:
‘n’ — Renders a number.
‘c’ — Renders a currency value.
‘p’ — Renders a percentage (number is multiplied by 100).
‘e’ — Renders exponential values.
Only available for the Number column type.
Specify the interval for adjusting the current value when using up and down arrows:
You can enter either an integer or a decimal number.
Here you can find properties specifically related to the Dropdown type columns.
Only available for the Dropdown column type.
Add a list of options to the Options property. Each option should be on a new line, as shown here:
Enable Allow user value to allow users to enter a custom value that is not included in the list of options:
Defines whether a user is allowed to select a single option or multiple options from the drop-down list:
Single Selection allows a user to select only one option from the drop-down list:
Multiple Selection allows a user to select multiple options from a drop-down list:
Note
In single selection mode the value is stored as a string.
In multiple selection mode the value is stored as an array of strings.
In this section, you can find basic examples of how to work with the control using JavaScript.
If you are not familiar with the JavaScript framework, get started with the JavaScript basics.
Note
The control is only accessible once the form is rendered, so all calls to the control must be inside fd.rendered event:
fd.rendered(function(){
//hide the control
fd.control('Control1').hidden = true;
//show the control
fd.control('Control1').hidden = false;
});
Get or set the DataTable control value. The control value is stored as an array of JavaScript objects, with properties for each column.
fd.control('Control1').value; // returns an array // set value with array of objects: var records = [{Date: new Date(), Text: 'Item A', Cost: 100 }, {Date: new Date(), Text: 'Item B', Cost: 200 }]; fd.control('Control1').value = records; // add new record to the DataTable using columns' InternalNames: var record = {Date: new Date(), Text: 'Item C', Cost: 300 }; fd.control('Control1').value.push(record);
Access HTML element inside the control in order to modify it, hide it, or do something else.
//access control's HTML var htmlControl = fd.control('Control1').$el;
Hide a control from a user. The control value can still be accessed and changed with JavaScript.
//hide control fd.control('Control1').hidden = true; //show control fd.control('Control1').hidden = false;
You can access the widget used by the control. The widget is based on Kendo UI Grid.
// get the widget fd.control('Control1').widget; // change the widget's configuration fd.control('Control1').widgetOptions = { sortable: false };
widgetOptions is the same as widget.setOptions({}) but can be defined before widget initialization.
It is possible to filter displayed values dynamically with the following code:
fd.control('Control1').widget.dataSource.filter({ field: 'Column1', operator: 'eq', value: 'Test' });
The supported operators are:
eq (equal to)
neq (not equal to)
isnull (is equal to null)
isnotnull (is not equal to null)
lt (less than)
lte (less than or equal to)
gt (greater than)
gte (greater than or equal to)
startswith
doesnotstartwith
endswith
doesnotendwith
contains
doesnotcontain
isempty
isnotempty
The last eight are supported only for string fields.
Based on Kendo’s dataSource filter property, check it out for more options.
Make a control required or optional:
//make control required
fd.control('Control1').required = true;
//make control not required
fd.control('Control1').required = false;
You can add a validation for a DataTable to verify the control’s data.
For instance, to make sure that a user has not added more than 10 records to the DataTable:
//make at least one record required
fd.control('Control1').addValidator({
name: 'Control1 validator',
error: 'No more than 10 records are allowed',
validate: function(value) {
//change this number to allow more/less records
if (value.length < 11) {
return false;
}
return true;
}
});
Note
You can adjust the number in the code to allow more records or add other conditions for a more complex validation.
You can add a validation for a DataTable column to verify the input data.
For instance, to limit the number of characters a user can enter:
fd.control('Control1').addColumnValidator('Column1', {
error: 'No more than 20 characters are allowed',
validate: function(value) {
return (value.length <= 20)
}
})
Note
You can adjust the number in the code to make more/less characters required or add other conditions for a more complex validation.
To populate DataTable control with rows of data, use the following code:
//select the DataTable control to populate
var dt = fd.control('Control1');
//specify information for rows using columns' Name property
var dtRows = [{
Product: 'Forms for SharePoint Online',
Price: 599,
Subscription: true,
Date: new Date()
},
{
Product: 'Charts for Office365',
Price: 399,
Subscription: false,
Date: new Date()
}
];
//assign rows to DataTable
dt.value = dtRows;
You can populate the data table from a file that is publicly available:
async function externalFile() {
const data = $.get('https://plumsail.com/assets/forms/data/source.json')
return data;
}
externalFile().then(function(data){
fd.control('Control1').value = JSON.parse(data)
})
The same way, you can populate the control from any external data source: a web service or a file.
To populate column values for each new row in a DataTable control, use the following code:
//select the DataTable control to automatically populate new rows
var dt = fd.control('Control1');
dt.widget.bind('beforeEdit', function(e) {
var model = e.model;
if (model.isNew()) {
model.set('Name', 'John Smith');
model.set('Email', '[email protected]');
}
});
To populate dropdown column of a DataTable control dynamically, use the code:
var dt = fd.control('Control1');
const populateDropDown = widget => widget.setDataSource({
data: ['Apple', 'Banana', 'Pear']
})
dt.$on('edit', (e) => {
const editMode = e.sender.getOptions().editable.mode;
//populate drop-down in a pop-up window for mobile devices
if (editMode === 'popup') {
const dropDown = e.container.find('input[name=Column1]').data('kendoDropDownList');
populateDropDown(dropDown);
//populate drop-down for desktop/tablet
} else {
if (e.column.field === 'Column1') {
populateDropDown(e.widget);
}
}
})
Sometimes, you might want to set fields automatically, without direct user input:
For example, the product prices are not something a user should be able to change. Instead, they can be set dynamically, depending on the selected product.
We’ll use a simple JS Object to store product prices, and automatically set unit price on product selection. Here is the code:
//we store prices in JS object
var merch = {};
//use bracket notation to accurately copy dropdown values
merch['Baseball cap'] = 9.99;
merch['T-shirt'] = 19.99;
merch['Key chain'] = 4.99;
var dt = fd.control('Control1');
//get a column by its name
const unitPriceColumn = dt.columns.find(c => c.field === 'UnitPrice');
//make column read-only
unitPriceColumn.editable = () => false;
dt.$on('change', function(value) {
if (value) {
for (var i = 0; i < value.length; i++) {
// populate UnitPrice column
value[i].set('UnitPrice', merch[value[i].Product] || 0);
}
}
});
Calculate total for a row:
Here is the code:
var merch = {}; merch['Baseball cap'] = 9.99; merch['T-shirt'] = 19.99; merch['Key chain'] = 4.99; var dt = fd.control('Control1'); // make LineTotal column (4th column) read-only dt.columns[3].editable = function() { return false }; dt.$on('change', function(value) { if (value) { // go through each row one by one for (var i = 0; i < value.length; i++) { // set the default values if (!value[i].Product) { value[i].set('Product', 'Baseball cap'); } if (!value[i].Quantity) { value[i].set('Quantity', 1); } // populate UnitPrice column value[i].set('UnitPrice', merch[value[i].Product] || 0); // calculate total for the row value[i].set('LineTotal', value[i].Quantity * value[i].UnitPrice || 0); } } });
If you’re getting an incorrect value in one of your fields, for example, in OrderTotal, make sure that the format is correctly configured and an appropriate number of decimals is selected:
Calculate total for the Amount and Line Total columns:
// make TotalPrice fields read-only fd.field('TotalPrice').disabled = true; var dt = fd.control('Control1'); dt.$on('change', function(value) { //variable to count total var priceTotal = 0.0; //if there are records in the table if (value) { //go through each row one by one for (var i = 0; i < value.length; i++) { //calculate total for columns if (value[i].LineTotal) { priceTotal += parseFloat(value[i].LineTotal); } } } //set the TotalPrice fields to the calculated values fd.field('TotalPrice').value = priceTotal; });
You can add a button to DataTable rows, which will allow you to duplicate them, like this:
Use the following code:
//select the DataTable control to add new column to
var dt = fd.control('Control1');
var columns = dt.widget.options.columns;
var customRowDataItem = null;
var isCustomAdd = false;
//specify what the column will be like
columns.push({
command: {
text: 'Copy row',
iconClass: 'k-icon k-i-copy',
click: function(e) {
e.preventDefault();
customRowDataItem = this.dataItem($(e.currentTarget).closest('tr'));
isCustomAdd = true;
this.addRow();
}
}
});
dt.widget.setOptions({
columns: columns
});
dt.widget.bind('edit', function(e) {
if (isCustomAdd && e.model.isNew()) {
isCustomAdd = false;
for (var i = 0; i < columns.length; i++) {
var field = columns[i].field;
if (field) {
e.model.set(field, customRowDataItem[field]);
}
}
e.sender.closeCell(e.container);
}
});
Add a custom button to the toolbar of the Data Table control by changing the Kendo UI Grid toolbar configuration:
var dt = fd.control('Control1');
dt.widget.setOptions({
toolbar: ['create', {
name: 'custom-button',
text: 'Button Name'
}]
});
$('.k-grid-custom-button').click(function(e) {
alert('Button clicked!');
});