Tabulator. How to enable and disable editing from js - tabulator

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.

Related

Tabulator - get another cell's value on click event

this one should be simple for tabulator experts (but not for me)...
i have a tabulator table. I've made one column, "edit" clickable as shown below. it works fine and returns the value of the cell i clicked. HOWEVER, that's not what i need. I need to get the value of ANOTHER cell in the same row (column "transactionID"). I know how you would do it in other languages, just use x and y values to move over 3 columns and get the value. but how is it done in tabulator? by the cloumn name? I can't find any example code on how to accomplish this.
This is the snippet from my tabulator init :
{title:"edit" , name:"edit", formatter:myformatter, cellClick:function(e, cell){alert("cell clicked - " + cell.getValue())}},
i just need to make it return value for "transactionID" instead of "edit"
and before anyone asks, no, i can't just make "transactionID" clickable. I need the clickable cell to be separate.
thanks for your help!
ok so since i got no answers to this question, i slogged thru and figured it out myself eventually. To save others time who run into this in the future, i am posting how i solved it. code with comments below :
// this goes in your tabulator column definitions. In my example, "edit" is a column
with an image button that on clicking, redirects to another page depending on what cell was clicked
{title:"" , name:"edit", formatter:openIcon, headerSort:false, cellClick:function(e, cell){
var re = cell.getRow(cell); // get the row of the cell that was clicked
var thenum = re.getData().id; // gets the value of column "id" in the same row
var theurl = "editTransaction.php?trans="+thenum; // creates my url
console.log(theurl); // perform whatever action you need to do. replace this.
}},
If you are using react-tabulator and you want to access some column data to perform a specific action ,here is the snippet for your help.
import { reactFormatter } from "react-tabulator";
// your React Component to use in a cell
function CustomFormatter(props: any) {
const rowData = props.cell._cell.row.data;
return <a onClick={() => alert(rowData.customField)}{cellData.customField }</a>;
}
const columns = [{ title: 'Custom', field: 'custom', align: 'center', formatter: reactFormatter(<CustomFormatter />) },
]

How to change tabulator Pagination buttons text and position

First part of the question is I want to simply change the original buttons "First", "Prev" and so on to some other text.
here is a link that shows original btns.
My second part of the question is how can i display the pagination in a footer out side the table
such as:
<table></table>
<div class:"footer">
pagination
</div>
There are several options you can use to change the pagination setup
Button Text
If you are looking to change the text, then the localisation system allows you to change any text for any part of the table, for full details see the Localization Documentation
var table = new Tabulator("#example-table", {
locale:"en-gb",
langs:{
"en-gb":{
"pagination":{
"page_size":"Page Size", //label for the page size select element
"first":"First", //text for the first page button
"first_title":"First Page", //tooltip text for the first page button
"last":"Last",
"last_title":"Last Page",
"prev":"Prev",
"prev_title":"Prev Page",
"next":"Next",
"next_title":"Next Page",
},
}
},
});
Button Position
If you simply want to change the position of the pagination element within the footer you can use CSS. The Styling Documentation contains a full list of classes used for styling the pagination elements.
To move the elements to the left hand side of the footer for example you would ned to use the following CSS:
.tabulator .table-footer{
text-align:left;
}
External Footer Element
if you want Tabulator to put the pagination elements into an element outside of the table, then you just need to pass the query selector for the element into the footerElement property in the table constructor. The Footer Layout Documentation contains full details on this.
In the example below i am assuming you have an element outside the table with an id of "my-footer" that you want the elements to appear in:
var table = new Tabulator("#example-table", {
footerElement:"#my-footer",
});
Here is the first part of the question:
$(".tabulator-paginator").find($(".tabulator-page[title='Next Page']")).text('>');
$(".tabulator-paginator").find($(".tabulator-page[title='Last Page']")).text('>>');
$(".tabulator-paginator").find($(".tabulator-page[title='First Page']")).text('<');
$(".tabulator-paginator").find($(".tabulator-page[title='Prev Page']")).text('<<');
As far as the second part tabulator have to keep the footer inside the table for it's javascript(the one the does pagination) to work. Hopefully in future updates it would let us do that, as it would provide more ability to custom the css.

Update bottomCalc-value, based on selection (if any)

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();
},
});

How to trigger editor programmatically

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();
});
},

jqGrid filtertoolbar not firing after grid resizing

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.

Resources