This seems like the simplest of requests but I can't seem to retrieve a set of rows from a Tabulator object.
Here's the code which instantiates the Tabulator object.........
function TabulatorInvitees(divId, companyName, userEmail) {
try {
var table = new Tabulator(divId, {
columns: [
{
title: "<div style='width:20%; float:left; text-align:left; color:blue; font-size:14px;'>Vendor Invitees</div>",
columns: [
{ title: "Id", field: "Id", visible: false },
{ title: "Added", field: "Added", visible: false },
{ title: "Changed", field: "Changed", visible: false },
{ title: "MarkedForExclusion", field: "MarkedForExclusion", visible: false },
{ title: "Email Address", field: "Email", widthGrow: 1, responsive: 0, hozAlign: "center", editor: "input", visible: true },
{ title: "First Name", field: "FirstName", widthGrow: 0.5, responsive: 1, hozAlign: "center", editor: "input", visible: true },
{ title: "Last Name", field: "LastName", widthGrow: 0.5, responsive: 1, hozAlign: "center", editor: "input", visible: true }
]
},
{
title: tabulatorAddUser(companyName),
field: "ManageRows",
widthGrow: 0.25,
responsive: 2,
hozAlign: "center",
formatter: "tickCross",
headerClick: function (e, row) {
row.getTable().addRow({ Id: 0, Added: true }, false);
},
cellClick: function (e, cell) {
tabulatorFreezeUnfreezeDelete(cell.getRow());
}
},
],
data: [],
height: "100%",
layout: "fitColumns", // required when using 'widthGrow'
placeholder: tabulatorPlaceholder(companyName), //display message to user on empty table
reactiveData: true, //enable reactive data
responsiveLayout: "collapse",
rowContextMenu: tabulatorContextMenu(),
});
table.on("rowTapHold", function (e, row) {
// from Tabulator documentation: "The rowTapHold event is triggered when a user taps on a row on a touch display and holds their finger down for over 1 second."
//e - the tap event object
//row - row component
tabulatorContextMenu();
});
table.on("tableBuilt", function () {
if (companyName.length > 0) {
table.setData(getDataSync({ caseSelector: "VendorMgmt_EmployeeList", companyCode: companyName, userEmail: userEmail }));
}
else {
table.setData([]);
}
});
}
catch (error) {
console.log(error);
}
}
The setData() function makes a call to a database function which returns three rows, similar to the following:
The following JQuery function is called when a radio button is clicked....
$(".vendorStatus").click(function (e) {
const status = e.target.value;
const tbls = Tabulator.findTable("#divVendorEmployees");
const tbl = tbls[0];
const tblRows = tbl.getRows();
console.log("tbls.length", tbls.length);
console.log("tblRows", tblRows);
});
The browser console indicates a table has been found (tbls.length = 1) but the tblRows array is empty:
I see the three rows in my Tabulator but I am not able to recall them programmatically. It seems like a simple problem which should have a simple answer.
I am using the most recent version of Tabulator (v5.4).
Any assistance is greatly appreciated.
After much searching, I finally came to the realization the DOM element associated with the Tabulator instance must be managed when attempting to refresh or replace data. I've implemented a method which allows me to delete and rebuild the DOM element each time I need to save data to my database and subsequently refresh my Tabulator instance.
Here's the code...
function refreshTabulatorObject(obj) {
let parentId = obj.parentId;
let childId = obj.childId;
//Empty and remove the current version of the [Tabulator] object.
const tables = Tabulator.findTable(childId);
if (tables.length > 0) {
var table = Tabulator.findTable(childId)[0];
table.setData([]);
}
//Remove the existing <div> from the DOM.
$(childId).remove();
//Re-create the <div> element for the [Tabulator] object and append it to the DOM.
var parentDiv = document.getElementById(parentId);
parentDiv.innerHTML = "";
var childDiv = document.createElement("div");
childDiv.setAttribute("id", childId);
parentDiv.appendChild(childDiv);
//Re-create the [Tabulator] object.
TabulatorInvitees("#" + childId, obj.companyName);
}
I'm sure those of you with a more intimate knowledge of Tabulator would likely suggest a more elegant method, however, this one appears to work and I've already spent far more time on this issue that I had anticipated. Unfortunately, elegance is not a luxury I can afford at this point.
I hope this solution might be of help to some other struggling soul.
In a modal context , Tabulator get data from api but do not render the table.
If I put a sleep of 500 milliseconds before return json from the api, the data show up.
<div class="form-group">
<div id="tablePersonnages"></div>
</div>
<script type="text/javascript">
var table = new Tabulator("#tablePersonnages",({
pagination: "local",
paginationSize: 10,
history: true,
ajaxURL: '#Url.Action("ObtenirPersonnages", "FicheHistorique")',
ajaxParams: { idFiche: '#Model' },
ajaxConfig: "POST",
layout: "fitColumns",
locale: true,
langs: {
"fr-fr": {
"ajax": {
"loading": "Chargement", //ajax loader text
"error": "Erreur" //ajax error text
},
"pagination": {
"first": "Début", //text for the first page button
"first_title": "Première page", //tooltip text for the first page button
"last": "Fin",
"last_title": "Dernière page",
"prev": "Préc",
"prev_title": "Page précédente",
"next": "Suiv",
"next_title": "Page suivante"
}
}
},
columns: [ //Define Table Columns
{ title: "Id", field: "Id", visible: false },
{ title: "Nom", field: "Nom", headerFilter: "input", headerFilterPlaceholder: " " },
{ title: "Prenom", field: "Prenom", headerFilter: "input", headerFilterPlaceholder: " " },
{ title: "Fonction", field: "Fonction", headerFilter: "input", headerFilterPlaceholder: " " },
{ title: "Naissance", field: "Naissance" },
{ title: "Deces", field: "Deces" },
{ formatter: link, width: 10 }
]
}));
On Modal Open Event
Call table.redraw(true) If still doesn't work put the redraw in a setTimeout()
I have API that GET json data with axios from another site. Site require login but i get this data with token. It looks like this:
"orders": [
{
"type": "some data",
"id": some data,
"number": "some data",
"startAddress": "<b>some data<br>some data",
"endAddress": "<b>some data</b><br>some data",
"voivodeshipOfUnloadingId": some data,
"distance": some data,
"rate": some data,
"supplement": some data,
"lumpSum": some data,
"sum": some data,
"loadingDate": "some data",
"status": 0,
"comments": "<p>some data</p>",
"isBlocked": false,
"isCompleted": false,
"index": 1
} ]
How get rid of html tags ?
Simple example: loop 'orders' array, then loop inner object properties and use string.replace with a regular expression to strip HTML tags.
Pay attention, this method mutates the original object, should you care.
const obj = {
'orders': [{
'type': 'some data',
'id': 'some data',
'number': 'some data',
'startAddress': '<b>some data<br>some data',
'endAddress': '<b>some data</b><br>some data',
'loadingDate': 'some data',
'status': 0,
'comments': '<p>some data</p>',
'isBlocked': false,
'isCompleted': false,
'index': 1
}]
};
for (order of obj.orders) {
for (const field in order) {
if (typeof order[field] === 'string') {
order[field] = order[field].replace(/(<([^>]+)>)/ig, '');
}
}
}
console.log(obj);
Output:
{
orders: [
{
type: 'some data',
id: 'some data',
number: 'some data',
startAddress: 'some datasome data',
endAddress: 'some datasome data',
loadingDate: 'some data',
status: 0,
comments: 'some data',
isBlocked: false,
isCompleted: false,
index: 1
}
]
}
I'm trying to bind a custom keys combination to perform a custom action like below but the key binding is not working. I even tried adding keybindings: true in the init settings but no change. There are no errors, warnings or notices in the console whatsoever.
I'm really not sure whether I'm using the .extendModule() correctly, though I have checked the docs already.
var rowContextMenu = function(e, row) {
// do something here
console.log("RIGHT CLICK: Context menu triggered");
}
var deleteRow = function(row) {
let rData = row.getData();
if(rData.hasOwnProperty('_children')) {
let cRows = row.getTreeChildren();
$.each(cRows, function() {
let r = this;
setTimeout(function() {
deleteRow(r);
}, 0);
});
}
row.delete();
};
Tabulator.prototype.extendModule("keybindings", "actions", {
"deleteSelectedRows":function(){ //delete selected rows
let selectedRows = this.table.getSelectedRows();
selectedRows.forEach(function(row){
deleteRow(row);
});
console.log('ROWS DELETED: Triggered with button keyboard');
},
});
Tabulator.prototype.extendModule("keybindings", "bindings", {
deleteSelectedRows:"shift + 9",
});
let nestedData = [
{name:"Oli Bob", location:"United Kingdom", gender:"male", col:"red", dob:"14/04/1984", _children:[
{name:"Mary May", location:"Germany", gender:"female", col:"blue", dob:"14/05/1982"},
{name:"Christine Lobowski", location:"France", gender:"female", col:"green", dob:"22/05/1982"},
{name:"Brendon Philips", location:"USA", gender:"male", col:"orange", dob:"01/08/1980", _children:[
{name:"Margret Marmajuke", location:"Canada", gender:"female", col:"yellow", dob:"31/01/1999"},
{name:"Frank Harbours", location:"Russia", gender:"male", col:"red", dob:"12/05/1966"},
]},
]},
{name:"Jamie Newhart", location:"India", gender:"male", col:"green", dob:"14/05/1985"},
{name:"Gemma Jane", location:"China", gender:"female", col:"red", dob:"22/05/1982", _children:[
{name:"Emily Sykes", location:"South Korea", gender:"female", col:"maroon", dob:"11/11/1970"},
]},
{name:"James Newman", location:"Japan", gender:"male", col:"red", dob:"22/03/1998"},
];
let table = new Tabulator('#my-tabulator', {
height:"400px",
layout:"fitColumns",
data: nestedData,
/**
* // Actual ajax configuration that won't work with test data (works perfectly with live data)
*
* ajaxLoaderLoading:'<div class="text-center" style="display:inline-block;"><img style="width:100px;" src="/path/to/my/spinner.svg"></div>',
* ajaxURL:"/path/to/my/data.json", //ajax URL
* ajaxConfig:"get", //ajax HTTP request type
*/
sortable: false,
selectable:true, //make rows selectable
dataTree:true,
dataTreeChildIndent:24,
dataTreeStartExpanded:[true, false], //start with first level expanded, second level collapsed
dataTreeCollapseElement:"<span class='expand-collpase-btn'>-</span>",
dataTreeExpandElement:"<span class='expand-collpase-btn'>+</span>",
rowFormatter:function(row){
if(row.getData().parent_id === null){
row.getElement().classList.add("root-node");
}
},
keybindings: {
deleteSelectedRows:"shift + 9"
},
rowContext:rowContextMenu,
columnMinWidth : 24,
columns:[
{title:"Name", field:"name", width:200, responsive:0}, //never hide this column
{title:"Location", field:"location", width:150},
{title:"Gender", field:"gender", width:150, responsive:2}, //hide this column first
{title:"Favourite Color", field:"col", width:150},
{title:"Date Of Birth", field:"dob", align:"center", sorter:"date", width:150},
],
/**
* // Actual column configuration that won't work with test data (works perfectly with live data)
*
* columns:[
* {title:"Col 1", field:"field_1", headerSort:false, titleFormatter:headerFilter, titleFormatterParams:filters, responsive:0,
* formatter:function(cell, formatterParams){
* //cell - the cell component
* //formatterParams - parameters set for the column
*
* let rowData = cell.getRow().getData();
*
* if(rowData['test'] == 'String 1' || rowData['test'] === false) {
* let cellUrl = $('<a></a>', {href: '/path/to/cell/item/itemid:'+rowData['id'], target: "_blank"}).html(cell.getValue());
* return cellUrl[0];
* }
* return cell.getValue(); //return the contents of the cell;
* },
* },
* {title:"Col 2", field:"field_2", headerSort:false, width:150,
* formatter:function(cell, formatterParams){
* //cell - the cell component
* //formatterParams - parameters set for the column
*
* let rowData = cell.getRow().getData();
*
* if(rowData['test']) {
* return '<span class="text-muted text-bold text-italic">String 1</span>';
* }
* return '<span class="text-italic">String 2</span>';
* },
* },
* {title:"Col 3", headerSort:false, field:"field_3", width:200, align:"right", titleFormatter:headerFilter, titleFormatterParams:filters, responsive:2}, //hide this column first
* {title:"Col 4", headerSort:false, field:"field_4", width:200, align:"right", titleFormatter:headerFilter, titleFormatterParams:filters},
* {
* title:"",
* headerSort:false,
* resizable: false,
* columns: [
* {title:"", width:24, headerSort:false, resizable: false, formatter:editButton, cssClass:'table-actions'},
* {title:"", width:24, headerSort:false, resizable: false, formatter:deleteButton, cssClass:'table-actions'},
* ]
* },
* ]
*/
});
$('#delete-rows-btn').on('click', function(e){
let selectedRows = table.getSelectedRows();
selectedRows.forEach(function(row){
deleteRow(row);
});
console.log('ROWS DELETED: Triggered with button click');
});
$('#reload-table-btn').on('click', function(e){
console.log('Table reloaded');
table.replaceData(nestedData);
});
/**
* I'm using custom CSS
* but let's ignore it for the sake of this demo
*/
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/tabulator-tables#4.2.7/dist/css/tabulator.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/tabulator-tables#4.2.7/dist/css/bootstrap/tabulator_bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/tabulator-tables#4.2.7/dist/js/tabulator.min.js"></script>
<a id="delete-rows-btn" href="javascript:void(0);" class="btn btn-sm btn-danger">Delete Selected</a>
<a id="reload-table-btn" href="javascript:void(0);" class="btn btn-sm btn-primary">Reload Table</a>
<div id="my-tabulator" class="table-bordered"></div>
you need to use shift + keyCodeand disable rowSelectable. My code works if you
focus on table
press Shift + 9 Key
var rowContextMenu = function (e, row) {
// do something here
console.log("RIGHT CLICK: Context menu triggered");
}
var deleteRow = function (row) {
let rData = row.getData();
if (rData.hasOwnProperty('_children')) {
let cRows = row.getTreeChildren();
$.each(cRows, function () {
let r = this;
setTimeout(function () {
deleteRow(r);
}, 0);
});
}
row.delete();
};
Tabulator.prototype.extendModule("keybindings", "actions", {
"deleteSelectedRows": function () { //delete selected rows
let selectedRows = this.table.getSelectedRows();
selectedRows.forEach(function (row) {
deleteRow(row);
});
console.log('ROWS DELETED: Triggered with button keyboard');
},
});
Tabulator.prototype.extendModule("keybindings", "bindings", {
deleteSelectedRows: "shift + 9",
});
let nestedData = [
{
name: "Oli Bob", location: "United Kingdom", gender: "male", col: "red", dob: "14/04/1984", _children: [
{name: "Mary May", location: "Germany", gender: "female", col: "blue", dob: "14/05/1982"},
{name: "Christine Lobowski", location: "France", gender: "female", col: "green", dob: "22/05/1982"},
{
name: "Brendon Philips", location: "USA", gender: "male", col: "orange", dob: "01/08/1980", _children: [
{name: "Margret Marmajuke", location: "Canada", gender: "female", col: "yellow", dob: "31/01/1999"},
{name: "Frank Harbours", location: "Russia", gender: "male", col: "red", dob: "12/05/1966"},
]
},
]
},
{name: "Jamie Newhart", location: "India", gender: "male", col: "green", dob: "14/05/1985"},
{
name: "Gemma Jane", location: "China", gender: "female", col: "red", dob: "22/05/1982", _children: [
{name: "Emily Sykes", location: "South Korea", gender: "female", col: "maroon", dob: "11/11/1970"},
]
},
{name: "James Newman", location: "Japan", gender: "male", col: "red", dob: "22/03/1998"},
];
let table = new Tabulator('#my-tabulator', {
height: "400px",
layout: "fitColumns",
data: nestedData,
sortable: false,
// selectable: true, //make rows selectable
dataTree: true,
dataTreeChildIndent: 24,
dataTreeStartExpanded: [true, false], //start with first level expanded, second level collapsed
dataTreeCollapseElement: "<span class='expand-collpase-btn'>-</span>",
dataTreeExpandElement: "<span class='expand-collpase-btn'>+</span>",
rowFormatter: function (row) {
if (row.getData().parent_id === null) {
row.getElement().classList.add("root-node");
}
},
keybindings: {
deleteSelectedRows: "shift + 57"
},
rowContext: rowContextMenu,
columnMinWidth: 24,
columns: [
{title: "Name", field: "name", width: 200, responsive: 0}, //never hide this column
{title: "Location", field: "location", width: 150},
{title: "Gender", field: "gender", width: 150, responsive: 2}, //hide this column first
{title: "Favourite Color", field: "col", width: 150},
{title: "Date Of Birth", field: "dob", align: "center", sorter: "date", width: 150},
],
});
$('#delete-rows-btn').on('click', function (e) {
let selectedRows = table.getSelectedRows();
selectedRows.forEach(function (row) {
deleteRow(row);
});
console.log('ROWS DELETED: Triggered with button click');
});
$('#reload-table-btn').on('click', function (e) {
console.log('Table reloaded');
table.replaceData(nestedData);
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/tabulator-tables#4.2.7/dist/css/tabulator.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/tabulator-tables#4.2.7/dist/css/bootstrap/tabulator_bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/tabulator-tables#4.2.7/dist/js/tabulator.min.js"></script>
<a id="delete-rows-btn" href="javascript:void(0);" class="btn btn-sm btn-danger">Delete Selected</a>
<a id="reload-table-btn" href="javascript:void(0);" class="btn btn-sm btn-primary">Reload Table</a>
<div id="my-tabulator" class="table-bordered"></div>
I'm trying to create a data table that shows images in the status column. I followed some examples from stackoverflow but it doesn't work. Does anyone know how to get the image to load in the column? The code below works but it doesn't seem like fomatter function is doing anything.
<script src ="http://yui.yahooapis.com/3.13.0/build/yui/yui-min.js"></script>
<script>
(function() {
YUI().use("datatable-sort", function(Y) {
var cols = [
{key: "Status", label: "Health Status",
formatter: function(el, oRecord, oColumn, oData) {
if (oData){
el.innerHTML = '<img src="info.png">';
}
},
sortable: true},
{key: "Company", label: "Issue", sortable: true},
{key: "Phone", label: "Contact"},
{key: "Contact", label: "Name", sortable: true}
],
data = [
{Status: "123", Company: "Company Bee", Phone: "415-555-1234", Contact: "Sally Spencer"},
{Status: "123", Company: "Acme Company", Phone: "650-555-4444", Contact: "John Jones"},
{Status: "123", Company: "Industrial Industries", Phone: "408-555-5678", Contact: "Robin Smith"}
],
table = new Y.DataTable({
columns: cols,
data: data,
summary: "Contacts list",
caption: ""
}).render("#sort");
});
})();
</script>
instead of doing what I did, do the following:
{key: "Status", label: "Health Status", formatter:"<img src='{value}' >", allowHTML: true},...
It worked out!