How to retain cells edited on setColumns()? - tabulator

I have tabulator working with excel like tabs at the bottom that change the columns shown. It also highlights any row that has been edited and highlights each individual cell that has been edited. But when I switch tabs, the edited rows maintains their highlights, but if I switch back to the previous tab, the cells that were edited are no longer highlighted.
this.tabulator = new Tabulator(this.$refs['example-table'], {
data: [],
height: "500px",
index:"title",
placeholder: "No Data Set",
footerElement: $("#table-controls").get(0),
columns: this.gtabColumns,
cellEdited: function(cell) {
if((_.isNil(cell.getOldValue()) || _.isEmpty(cell.getOldValue()))
&& (_.isNil(cell.getValue()) || _.isEmpty(cell.getValue()))) {
return;
}
$(cell.getElement()).css("background-color", "#67f165");
$(cell.getRow().getElement()).css("background-color", "#d1fbd0");
},
});

This is happening because you are trying to directly manipulate the elements in the table from inside the cellEdited function.
Because Tabulator uses a virtual DOM it is not safe to try and manipulate any elements inside the table directly. You should only change the cell element in the formatter in the column definition or the rowFormatter for rows. anywhere else is unsafe.
In your case you would want a cell formatter like this:
var editedCellFormatter = function(cell){
if(cell.oldValue !== null){
cell.getElement().style.backgroundColor = "#67f165";
}
return cell.getValue();
}
Which you can then assign in the column definition:
{title:"Name", field:"name", formatter:editedCellFormatter}

Related

Shouldn't table.undo() clear any cell.isEdited() flag when the undo "undoes" a cell edit?

In Tabulator - when using the history module and - the function undo(): It seems that the cell flag isEdited() doesn't get cleared when the undo undoes a cell edit.
I want to mark all edited cells in a table through CSS, but after I did an undo() on the table I noticed that the edit markings were not removed - even though the cells got "undone" as they should.
To mark edited cells, I use a function that look like this:
const setEditedCellsVisibility = () => {
document.querySelectorAll(".tabulator-cell").forEach( element => {
element.classList.remove('edited');
})
//(The "Table" is set up elsewhere, but is a normal tabulator table)
Table.getEditedCells().forEach( cell => {
cell.getElement().classList.add('edited')
})
}
Do I need to "manually" clear the flag for cell.isEdited() after each Table.undo() call?

Select all content when Tabulator editor opens

I have a Tabulator (4.9.3) with values that use an editor of type text. As I tab through the table, I want each value to be selected so I can overwrite it without having to clear it first. I have tried putting the usual range selection code into the cellEditing callback and the Tabulator source code where the input gets created. Here is one variation of the code (I can't show them all because the node differs based on context):
try {
if (document.selection) {
// IE
var range = document.body.createTextRange();
range.moveToElementText(input);
range.select();
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(input);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
} catch (e) {console.log(e);}
If I double-click on the cell, the value selects as desired. How can I get this to work with keyboard navigation as well?
Since the editor is not assigned an id, finding a selector that could find it reliably was problematic without editing the source code. Since I was going to have to edit the source, I ended up adding the following line to the onRendered function of the input element under Edit.prototype.editors.
input.select();

Tabulator - Disable editing for specific field

I have a table in Tabulator where all fields are Editable.
I would like to be able to switch the edit function on and off for different fields after the table has loaded.
I can hide the column: table.hideColumn("r1");
but it would be great if I could disable the editing.
As a bonus i'd also like to reformat the disabled column (change the background colour)
var table = new Tabulator("#table", {
height:"90%",
layout:"fitData",
ajaxURL:"data.php",
placeholder:"Data Loading...",
history:true,
cellEdited:function(cell){console.log("cell changed: (" + cell.getOldValue() + ") [" + cell.getValue() + "] - field: " + cell.getField() + " - id: " + cell.getRow().getIndex());},
columns:[
{title:"id", field:"id", sorter:"number", visible:false},
{title:"1", field:"r1", sorter:"number", editor:"input"},
{title:"2", field:"r2", sorter:"number", editor:"input"},
{title:"3", field:"r3", sorter:"number", editor:"input"},
{title:"4", field:"r4", sorter:"number", editor:"input"},
],
});
Many Thanks
AMEND - Added fiddle
In order to change bg cell color and also its font color use:
cell.getElement().style.color= "#ffffff"; //CHANGE CELL WHITE FONT
cell.getElement().style.backgroundColor = "#e68a00"; //CHANGE CELL BG COLOR
inside tabulator's title declaration..
for disabling editing try an object array with states: Let's say we have 3 columns and want only column 3 to be edited...
var isDisabled=["","","input"];
so you can use:
{title:"1", field:"r1", sorter:"number", editor:isDisabled[0].toString()},
{title:"2", field:"r2", sorter:"number", editor:isDisabled[1].toString()},
{title:"3", field:"r3", sorter:"number", editor:isDisabled[2].toString()}
Now you are ready to access these states directly in your array to change tabulator's edit status on the runtime!
Hope that helps!
[UPDATE1]
I've found this approach on Tabulator's Documentation:
var editCheck = function(cell){
//cell - the cell component for the editable cell
//get row data
var data = cell.getRow().getData();
return data.age > 18; // only allow the name cell to be edited if the age is over 18
}
//in your column definition for the column
{title:"Name", field:"name", editor:"input", editable:editCheck}
You can add a differed approach on every column and you can set corresponding criteria. i Also noted that once tabulator loads its data there is no way of disabling/enabling cell editing. But with the above method you define edit-ability before loading data!
[UPDATE2]
Im using cell.getColumn().getField(); to access columns name for triggering IF statement
var editCheck = function(cell){
var data = cell.getRow().getData();
if (incomingValue === 0){
console.log("Enable All");
return data;
}
if (incomingValue === 2 && cell.getColumn().getField()==="r1"){
console.log("Disabled col1");
return data.r1!==incomingValue; //FOR ENABLING EDIT TO OTHER COLUMNS EXCEPT THIS ONE
}
//... Here all IFs for the rest columns
};

Tabulator - Having Column Header Resize when Font Size Changes

I am using Tabulator and the default "fitData" function to size the cells. This works exactly as intended when I a) Have a default font size set and b) change the row font size using the rowFormatter:
rowFormatter:function(row){
var rowData = row.getData();
row.getElement().style.fontSize = config.body_font_size + "px";
The above works, however, when I want to change the font size of the column titles:
var curHeaders = document.getElementsByClassName("tabulator-col");
for (var i = 0; i < curHeaders.length; i++) {
curHeaders[i].style.fontSize = fontSize.toString() + "px";
}
This changes all the column font sizes, but does not resize the column width appropriately. Is there a different class where I should assigning the font? Is there a way to apply this in a similar way to the rowFormatter?
You shouldn't try and programatically alter elements inside Tabulator from outside the table. Because Tabulator uses a virtual DOM these changes can be overwritten at any point without notice.
If you need to format column header titles you should use a titleFormatter in the column definition for the column you want to change:
//define custom formatter
var customFormatter = function(cell, formatterParams, onRendered){
//set font size
cell.getElement().style.fontSize = fontSize.toString() + "px";
return cell.getValue();
}
//in the column definition for a column
{title:"Name", field:"name", titleFormatter:customFormatter },
Full documentation on how to use formatters can be found here: http://tabulator.info/docs/4.0/format
If you need to keep using your approach then you can call the table redraw function to force the table to be rebuilt:
table.redraw(true);
Is there a reason you need to change it at run time rather than just making the changes in CSS?

LWUIT Table Layout embedded TextAreas

my goal is to display a Table through parsing an XML file.
I'm using a SAX Parser and the content has multirows and I want
the table width to fit to the display. Of course Y_AXIS scrolling would be ok.
Right now, I'm using the HTMLTableModel of src/com/sun/lwuit/html/ and it's corresponding HTMLTable. For this I declared it's methods public so I can access them. This works fine so far. This allows me to declare tables without knowing their size prematurely.
To allow multirows, I'm embedding TextAreas in the Cells.
Now the problem: The HTMLTable t needs t.setScrollableY(true), or else not all rows are shown.
This causes the table to be a bit to large in X direction, so the right border isn't shown.
Also the bottom border isn't shown all the time.
The container in which the table is embedded has BorderLayout.Y_AXIS.
Things I tried:
t.setPreferredW(mainContainer.getLayoutWidth()); This does reduce the size of the table, but then the table doesn't show all it's rows, like without t.setScrollableY(true).
t.setLayout(new BoxLayout(BoxLayout.Y_AXIS)) this causes an java/lang/ClassCastException.
Any ideas? Thanks in advance.
Excerpt from my code:
} else if (qName.equalsIgnoreCase("td")) {
if (sb.length() > 0) {
String sbt = new String(sb);
sb.delete(0, sb.length());
TextArea c = new TextArea(sbt);
c.setEditable(false);
c.getStyle().setFont(smallFont);
table.addCell(c, false, null);
}
} else if (qName.equalsIgnoreCase("tr")) {
debugPrint("Row closed.");
table.commitRow();
} else if (qName.equalsIgnoreCase("table")) {
HTMLTable t = new HTMLTable(table);
//without scrollable Y not all table rows are shown
t.setScrollableY(true);
//t.setPreferredW(screenWidth);
//this is verboten.
t.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
mainContainer.addComponent(t);
tableBool = false;
You can't change the layout of the table from table layout otherwise it will not be a table.
It should be possible to get the table to fill the width of a parent BoxLayout_Y by assigning width percentages to table columns up to 100% e.g. for a 3 column table return assign 33, 33 & 44.
This can be achieved by subclassing table and overriding the method:
protected TableLayout.Constraint createCellConstraint(Object value, int row, int column) {
TableLayout.Constraint c = super.createCellConstraint(value, row, column);
c.setWidthPercentage(whateverYouWant);
return c;
}

Resources