I just found Tabulator, and i love it. I'm currently using version 4.5. The bottomCalc-function isuseful, however, i would like it to be updated, based on the selection of row(s).
Is there a native option i've missed, or, should it be done manually, fx. triggered by the row-selections?
Column example:
{
title: 'Offline Amount',
field: 'offline',
bottomCalc: 'sum',
formatter: 'html',
align: 'center',
width: 150,
},
And selectField: true for columns.
Currenly, without updated bottomCalc:
And, i would like it to be updated, based on the selection (if there is any).
Update:
I guess the rowSelectionChanged-option, will be the best way to handle the update of .tabulator-footer .tabulator-calcs-holder, but i'm still unsure about, how to do that part.
If it's a question of looping through the selected values, calculate the sum, and update the value - or if i'm able to use another event, reuse a specific function, or yet another thing.
There is no built in way to achieve this but there may be a work around.
You could store a property in the row data that stores the selected state of the row. You could then use the rowSelected and rowDeselected callbacks to change this value.
You could then use a Custom Calculation Function to then generate the sum of the column values for the rows where the data object has a selected property of true.
Update
As of version 4.6, there is now a recalc function you can call on the table, so you could set up your calc function as outlined in the answer above and then use the rowSelectionChanged callback to trigger the update:
var table = new Tabulator("#example-table", {
rowSelectionChanged:function(data, rows){
table.recalc();
},
});
Related
Using Tabulator, if you have a 'select' editor and want it to link to values 'Male' and 'Female' but underneath male and female are values from another physical database table with id values of 1 and 2 (which are different than the 'row' id), whats the best way to do something like this?
The 'select' editor has ways to specify the display of items in the drop down and a literal display of the selected value, but no place for a hidden (not displayed) underlying ID of the selected value to pass when saving the data.
We could wrap the select data values in divs with a data attribute for the selects values ids and then pass that when updating, but are not sure this is the best option considering how Tabulator works. We could also just pass the raw selected value and then look it up on the server to get the associated ID, but that seems like a lot of overhead and tightly couples the server to the client, which wouldn't work for something like a 3rd party API where we have no server control.
Any thoughts on how best to handle something like this are appreciated!
The select editor allows for values to be passed in a number of ways, including specifying both the items value and its user visible label
If you want to show a different lable to the value you want to store, you can pass in an object, where the key of each property is the value that will be stored if it is selected, and the value of each property will be the lable displayed for it in the list.
{title:"Name", field:"name", editor:"select", editorParams:{
values:{
"steve":"Steve Boberson",
"bob":"Bob Jimmerson",
"jim":"Jim Stevenson",
}
}}
For more complex option lists you can use an array of objects, that allows you to define option groups, and disabled options.
{title:"Name", field:"name", editor:"select", editorParams:{
values:[
{ //option group
label:"Men",
options:[ //options in option group
{
label:"Steve Boberson",
value:"steve",
},
{
label:"Bob Jimmerson",
value:"bob",
},
]
},
{ //option group
label:"Women",
options:[ //options in option group
{
label:"Jenny Jillerson",
value:"jenny",
},
{
label:"Jill Betterson",
value:"jill",
},
]
},
{//ungrouped option
label:"Other",
value:"other",
},
]
}}
For full details on how to use this editor, checkout the Editor Documentation
Finally figured this out. You need to use the lookup formatter to display the text value using the same params as the select editor. This is not obvious since none of the select editor examples in the docs show use of it. Anyway, here is a simple example showing it in both directions. Of course you would want to abstract the data out instead of literally duplicating it, but here to help show the literal use, it is duplicated:
{
title:"Example",
field:"example",
editor: "select",
editorParams:{
"1": "Cute",
"2": "Fine",
"3": "Scary",
},
formatter:"lookup", // display option, but store value
formatterParams:{
"1": "Cute",
"2": "Fine",
"3": "Scary",
}
}
I am trying to set a default headerFilter value before the table loads. I tried all the way up to tableBuild callback. Still getting 2 calls to the API, one for the regular non-filtered data then one with the default filter. The column initialValue and defaultValue params do not seem to affect filterHeaders which is why I am going down this rabbit hole.
tableBuilt: function () {
console.log("tableBuilt");
this.setHeaderFilterValue("status", "Inactive");
}
Try the initialHeaderFilter value during table creation.
initialHeaderFilter: [{field: 'fieldName', value: 'filter value'}]
http://tabulator.info/docs/4.6/filter#header
Here is a working example.
https://jsfiddle.net/nrayburn/r319zaep/40/
I'm using tabulator (fantastic thing), which has a built in, in line editing functionality.
The thing is though, it's either on or off by having the editor tag on a column basis.
You can disable the editor for a given cell as well.
What I'm trying to do is to have the table displayed as read only so to say.
Then click on a 'edit' button (which is in my table and I capture the click). That would in turn enable the inline, built-in editor functionality for that raw only.
Then I click a save button, write the updated data back to my DB and make the row read-only again.
So, with tabulator 4.2, I'd be looking for something like
var usrtable = new Tabulator("#usrtable", {
ajaxURL:"/account/cgi-bin/getallusers.php",
resizableColumns:false,
tooltips:true,
history:true,
pagination:"local",
paginationSize:10,
paginationSizeSelector:true,
reactiveData:true,
selectable:true,
initialSort:[{column:"username", dir:"asc"},],
columns:[
{ formatter: editIcon, width: 40, sortable: false, align: "center", cellClick: function (e, cell) {
var id = cell.getRow().getData().id;
row(id).editable=true;
/\/\/\/\/\/\/\/\/\/\/\
}
},
{title:"Id", field:"id", visible:false},
{title:"Username", field:"username", width:80, editor:"input"},
{title:"Password", field:"password", width:70, editor:"input"},
{title:"Role", field:"role", width:70, align:"center", formatter:"plaintext", editor:"select", editorParams:{values:["user","admin"]}},
{title:"Change passwd", field:"changepasswd", width:90, align:"center", formatter:"tickCross", sorter:"boolean", editor:true},
],
});
Is that somehow possible or do I have to re-invent the wheel? i.e. create a model to edit the data outside the table?
What I have tried.....
Once rendered, a cell looks like this:
<div class="tabulator-cell" role="gridcell" tabulator-field="username" tabindex="0" title="test" style="width: 80px; height: 29px;">test</div>
And when you click on the cell, it becomes editable and the class 'tabulator-editing' is added to the div.
So..... I though I could 'just' catch the click event and do something like this:
$(".tabulator-cell").on("click",function(){
($this).removeClass("tabulator-editing");
});
that didn't work so tried this:
$(".tabulator-cell").on("click",function(e){
e.preventDefault();
});
that didn't work either.
When doing this:
$(".tabulator-cell").on("click",function(){
alert("cell clicked");
});
it actually never fires... :-(
Either I'm doing something wrong or really do not know where to go from here....
This can be achieved with Tabulator's Optional Editing:
// column definition
{ title:"Name", field:"name", editor:"input", editable:editCheck }
var editCheck = function (cell) {
var isEditable = cell.getRow().getElement().classList.contains('isEditable');
return isEditable;
}
With this logic in place, you simply need to toggle isEditable class on the appropriate Tabulator Row.
In the documentation under Column Setup, there is a Data Manipulation option called editable.
http://tabulator.info/docs/4.2/columns#definition
editable - callback to check if the cell is editable (see Manipulating Data for more details)
I haven't experimented with it myself, but it appears as if this is only called when initially rendering the table, so you may have to force a re-render with table.redraw(true) when the user clicks the Edit and Save buttons.
You could also just use your cellClick event and call cell.edit().
So, I also got feedback from Oli who is the developer for Tabulator.
The short answer is that there is no option to enable editing at the row lever as I feared.
Furthermore, the option will not be added due to multiple factors.
In other words, what I'm trying to do is not available out of the box and the editing is to be done at the cell level.
There is no option for this in the tabulator. But if you want to disable a cell from editing, you can simply remove all the tabulator applied classes for the particular cell. For eg., if you want to make the last row edit disabled, you can use something like this,
$(".tabulator-row:last .tabulator-cell").removeAttr("role tabulator-field tabindex title");
I know this is a old question but my answer can be useful for visitors come here (like me) in future..
We have also a similar requirements, and we ended up by this solution. We have added "editor" in every column with another attribute "editable". In "editable", we are checking whether the row is selected or not, if row is selected then field can be editable otherwise not editable.
Other than that we have also used a "rowSelected" and "rowDeselected" to show/hide save button and on "rowSelected", we are checking that only 1 row is selected at a time.
I have set up a producttable (kind of a shopping-cart) with one editable column (product amount) like this :
{
title:"Aantal",
field:"product_amount",
align:"center",
responsive: 3,
validator:["required","numeric"],
editor:amountEditor,
cellEdited:recalcPrices,
validator:["required","numeric","min:1","max:10"]
},
I am using a custom jquery amountEditor because this one looks somewhat nicer than the builtin editor. Rows are added to the shopping cart tabel (copied from another producttable) by a button click. Everything works fine but I would like that the user doesn't have to click on the editable columnfield himself. So the only one editable field should be triggered automatically / programmatically after the row is added to the table.
I think I have to combine these commands somehow in the table definition:
rowAdded:function(row){
var cell = row.getCell("product_amount");
cell.edit();
},
I tried everything but I cannot find the right combination to get this work. I can get var rowElement = row.getElement(), however var cells = row.getCells() or var cell = row.getCell(column) look empty. Any help is much appreciated.
You need to scroll to the row using the scrollTo function on the row component to ensure it is visible before you can trigger an edit on the cell, so your rowAdded callback wants to look like this:
rowAdded:function(row){
row.scrollTo().then(function(){
row.getCell("product_amount").edit();
});
},
I have fixed row numbers to 10 for my subgrids, but if reccount is less than 10 I would want to adjust height subgrid to "auto" or "100%".
So here is my code for this subgrid :
// SUBGRID FOURTH LEVEL
var subgrid_table_id = subgrid_id+"_d",
pager_id = "p_"+subgrid_table_id;
$("#"+subgrid_id).append("<table id='"+subgrid_table_id+"' class='scroll'></table><div id='"+pager_id+"' class='scroll'></div>");
$("#"+subgrid_table_id).jqGrid({
url:"sg31b.php?id="+row_id+"&clt="+clt,
datatype: "json",
idPrefix:"sgd_",
colNames: ['Id','Article','Désignation','Marque','Equivalence'],
colModel: [
{name:'e.id',index:'e.id',hidden:true},
{name:'a.code',index:'a.code', width:100},
{name:'a.descr',index:'a.descr', width:450},
{name:'k.code',index:'k.code', width:80},
{name:'e.equiv',index:'e.equiv',width:100}
],
pager: pager_id,
sortname: 'a.code',
hiddengrid:true,
scroll:true,
height:230,
rowNum:10,
autowidth:true,
caption:'4 - EQUIVALENCE ARTICLES',
gridComplete:function(){
sortDataCol(this);
if($("#"+subgrid_id+"_d").jqGrid('getGridParam','records') < $("#"+subgrid_id+"_d").jqGrid('getGridParam','rowNum')){
$("#"+subgrid_id+"_d").jqGrid('setGridHeight','100%');
}else{
$("#"+subgrid_id+"_d").jqGrid('setGridParam',[{npage:1}]).jqGrid('setGridHeight',230);
}
}
});
$("#"+subgrid_table_id).jqGrid('navGrid',"#"+pager_id,{search:false,add:false,edit:false,del:false});
$("#"+subgrid_table_id).jqGrid('filterToolbar',{stringResult: true,searchOnEnter : false});
fullInputCss();
and the snapshot of result for less than 10 filtered rows :
Now if I press Backspace in search field to obtain more rows, it seems that search doesn't fire because Firebug doesn't show any trace of request :
If I delete added 'setGridHeight' lines in gridcomplete, all runs fine !
I think that one more time I'm wrong in my coding and understanding how jqGrid runs.
Please could someone give me some way to solve this trouble ?
Many thanks in advance. Have a nice day. JiheL
I suppose that the origin of the problem could be id duplicates on your page. Just now I wrote the answer on another your question where I described the problem detailed.
Current implementation of jqGrid (version 4.4.5) has problem in the code of filterToolbar which constructs id for input fields of the filter toolbar based on the following rule:
id="gs_" + cm.name
(see the line of code). It means that the id of the input field for the column a.code will be gs_a.code for every subgrid which you use. So you can have id duplicates.
So I recommend you redesign the naming concept in your code. You can use for example
name: row_id + "a_code", index: "a.code"
In the way the value like "a.code" will be still send during sorting of the grid, but you will have no id duplicates. In some scenarios (is you use repeatitems: false in jsonReader) you could need to use additional jsonmap attribute, but you don't need it in you current code.