How to programmatically disable cells in a Ext.grid.EditorGridPanel - javascript

I have a web application that uses ExtJS 4 that incorporates a Ext.grid.EditorGridPanel.
One of the columns of the Ext.grid.EditorGridPanel has a combobox editor that I would like to disable programmatically when the store loads based on the value of another field in the store.
It seems like this should be pretty simple - but so far nothing seems to work.
When the Grid's store loads, I have a listener to check each row and disable the combobox in index 4 depending on the value of another field.
The only thing that I can't get to work is actually disabling the combobox.
Any suggestions?
Here is the psuedo-code. Thanks in advance
listeners: {
'load': function(st, records, options) {
var view = getMyEditorGridPanel().getView();
for (var i = 0; i < this.getCount(); i++) {
if (store.getAt(i).get('setDisabled') === 'Y') {
//The cell at index 4 has a combobox editor - I CAN'T GET IT TO DISABLE!!
view.getCell(i,4).setDisabled(true);
}
}
}

From my point of view you have two different things you need to manage here:
Cell Styling, the way a cell looks when not being edited (either is enabled or disabled)
Editor Availability, how to react when a cell is about to be edited (should be possible to edit the cell)
Cell Styling
For the first one I would advice to provide a style to each cell in order to make it look disabled, this can be achieved during rendering time instead trying to do it when the store loads (btw nothing ensures you that the grid items have been fully rendered just after getting the load event callback). You can return a custom class per row by providing an implementation to Ext.grid.ViewView.getRowClass
viewConfig: {
getRowClass: function(record, rowIndex, rowParams, store) {
return record.get("disabled") ? "mail-disabled" : "";
}
}
Editor Availability
You will also need to handle the Ext.grid.plugin.CellEditingView.beforeedit event and provide a custom logic to determine when the editor will be available
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1,
listeners: {
beforeedit: function(editor, e, eOpts) {
return e.record.get("disabled") == false;
}
}
})]
You can find a working example of both solutions here, hope it helps to solve your problem.

Related

Dynamically change searchable datatable column property

I have to change in one function, after the initialization of a datatable, bSearchable property of a column. I need first to enable and then disable it.
I found an example for visibility:
$(document).ready(function() {
var table = $('#example').DataTable( {
"scrollY": "200px",
"paging": false
} );
$('a.toggle-vis').on( 'click', function (e) {
e.preventDefault();
// Get the column API object
var column = table.column( $(this).attr('data-column') );
// Toggle the visibility
column.visible( ! column.visible() );
} );
} );
Can something similar be used also in my case? Something like column.seachable?
This is an old question, but one that cost me several hours to research the answer to... mostly based on my lack of JS skill though.
The usecase was that I have a table with an ID column that is a GUID. This Id is seldom used uses a lot of space, so it's hidden and not searchable by default. But for internal users who might have access to logs or the database, we need to be able to search the ID column as well.
I added a checkbox for these users and it should change visibility and the searchable attribute of the ID column.
My solution is based on another question regarding searching on columns. But in this question, the search was only intended on one single column and not on all searchable columns as well (normal DataTable.search() API). Sadly, to change the searchable property, there seems to be no public API. If you change the searchable property, you have to invalidate the data in the table afterwards, otherwise the columns data will still be / not be present in the tables aoFilterData. This forces the table to reload the data from the datasource (in this case, the DOM).
I had a lot of problems with registering the eventhandlers at the right place. The filter field is not present at the first draw event of the table, so i had to register the handlers in the init event that is fired after the table is fully initialized.
var userTable;
var idSearchCbx;
var searchField;
$(document).ready(function () {
userTable = document.getElementById("table-users");
if (userTable) {
userTable = $("#table-users").DataTable(
{
"columnDefs": [
{
//First column invisible and not searchable by default
"targets": [0], //first column = ID
"visible": false,
"searchable": false
}],
//Other initialization options
); //Table creation
userTable.on("init",
function () {
$("input[type='search']").on("change cut input keypress keyup paste search recheck",
function () {
var searchValue = $(this).val();
userTable.search(searchValue).draw();
//width attribute is calculated and added to the table
//it loses 2 pixels everytime the checkbox is checked/
//unchecked somehow - so delete it
document.getElementById("table-users").removeAttribute("style");
});
idSearchCbx = $("#cbx-search-id");
idSearchCbx.on("change",
function () {
if (this.checked === true) {
//this makes the first column searchable, not official API
userTable.context[0].aoColumns[0].bSearchable = true;
//make it visible as well, official API
userTable.columns(0).visible(true);
//invalidates cached table data so that the column values are
//added to the filterdata
userTable.rows().invalidate().draw();
} else {
userTable.context[0].aoColumns[0].bSearchable = false;
userTable.columns(0).visible(false);
userTable.rows().invalidate().draw();
}
//trigger the normal search again so that the
//filter is / is not applied to the first column
$("input[type='search']").trigger("recheck");
});
}); //DT on init
} //table present
});//document ready
I assume context is related to settings(), so keep in mind that names in the context might change and this is most likely not version-stable even in minor releases. But I didn't find any other way. Hope it helps someone.

Can I change a Kendo UI Grid's foreign key values?

I have a Kendo grid that uses a drop down of foreign key values. I need to be able to update these foreign key values based on the value of an external drop down on my page. I am able to set the drop down's new values with Javascript, but the grid itself has the old values in that foreign key column. I need to be able to set those values as well so the drop down works in edit mode. Has anyone attempted to do this or seen an example of doing this? I have searched a ton for this and can't find anything.
Taken from telerik forum,
function onGridEdit(e){
var ddl = e.container.find("[data-role='dropdownlist']");
if(ddl){
ddl.getKendoDropDownList().bind("change", function(evt){
e.model.set("ProductData.ProductValue.MasterDataText", this.text());
});
}
},
Alternatively, then you define drop down as an editor for a grid column, you can
do like this:
var customDdlEditor = function (container, options) {
//some code...
change: function (e) {
options.model.Name = this.value();
},
}

Get coordinates with handsontable wider than the screen

I have a grid with handsontable but this grid is wider than the screen. Here is a capture of what it looks like :
As you can see, I have a scroll bar because the grid is too wide.
The user insert some data in this grid and I make a request in ajax to test the content (required field, numeric field, ...) When there is an error, I return a number to know which cell is incorrect. I use this number like that :
$(cells).eq(jsonobject[item]-11).css("background-color","red");
With the .eq function I can select the cell I want. But when the grid is wider than the screen, I feel that the index of each cell is moved.
Here is a wonderful sketch of what I think :
So the indexes are dependants of the screen but not of the grid.
How can I overcome this problem please ?
EDIT :
The code where I declare my hot :
var container = document.getElementById('tab_traitement');
var hotTraitement = new Handsontable(container, {
data: data_traitement,
stretchH: 'all',
minSpareRows: 1,
observeChanges : true,
rowHeaders: false,
colHeaders: false,
contextMenu: true,
height: 550,
... //more options
In the ajax return, I get an array of values with some indexes where the data is incorrect and I try to color the cell in question. So I tried like that :
for(var i=1; i<(data_traitement[0].length);i++ )
{
for(var item in jsonobject)
{
if((item % 2 ) == 0) //Si l'indice est pair, on affiche la couleur
{
hotTraitement.getCell(i,jsonobject[item]-j).css("background-color","red"); //Here, firebug tells me "hotTraitement is undefined"
}else
{
$(cells).eq(jsonobject[item-1]-1).qtip({
content : '<div id="bulle">'+jsonobject[item]+'</div>',
position: {
adjust: {
x: -100
}
},
style: {
classes: 'myCustomClass',
def: false
}
});
}
}
j = j+3; //Just to loop through the rows (I have 3 cells in a row)
}
Well to start off, there's virtual rendering happening horizontally meaning that if you were to have a table with many many columns, most aren't being rendered therefore jquery will never find them.
Now, to do this more efficiently, I would simply get the cell using the HOT methods included:
hot.getCell(row,col);
This returns to you the TD after which you could attempt to do the css like you were asking.
I don't think this would be the best way to go, however, because physically modifying the DOM doesn't work well with Handson given that it re-renders pretty frequently. Instead, you should be setting the custom renderers on each cell to respond to your validation efforts. A simplistic solution is to have an array with cell coordinates which should be marked as "invalid". The custom renderer could then ask if the current cell coordinates are in this array and if so, apply your css logic as you did above.
And just FYI, Handson has wonderful validation functionality built in which I highly recommend using. It will apply a class name for you if it fails validation so there wouldn't even be a need to do any fancy cell finding, just add the class you want and in your CSS file attach whatever style you want.

How to update ZK Grid values from jQuery

I have three Tabs and in each tab, I have a Grid.
The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:
<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">
The rows are constructed from Doublebox objects. The data is populated successfully.
The Problem:
I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.
As example let's say that the user edits first cell on the first row and the value should be
propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes).
I am using jQuery to do this value propagation and it works OK.
I am passing the jQuery as follows:
doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);
This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.
The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones.
I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.
Code of how I extract the Grid values:
Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i);
The model for my Grid is a List of MyCustomRow:
myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));
I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)
Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!
Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.
The ways to solve your problem.
Use the "ZK-Way":
Simply listen at server-side and chage things there.
I am not sure if not selected Tabs
are updateable, but I am sure you could update the Grid
components on the select event of the Tab.
Fire an zk-event your self:
All you need to know, is written in the zk doc.
Basically, you collect your data at client side, send
an Event to the server via zAu.send() extract the
data from the json object at serverside and update your Grids
I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.
I post the solution we came up with:
This is the javascript attached to each Doublebox in the Z-Grid
//getting the value of the clicked cell
var currVal = jq(this).val();
//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');
// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else { //otherwise we assume this is the last cell of the current tab
//So we get the current row, because we want to edit the cells in the same row in the next tabs
var currRow = jq(this).parents('tr').prevAll().length;
//finding the next cell, on the same row in the hidden tab and applying the same logic
objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
if (objCellsHiddenTabs.length) {
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
}
}
The java code in the RowRenderer class looks something like this:
...
if (someBean != null) {
binder.bindBean("tBean", someBean);
Doublebox box = new Doublebox();
setDefaultStyle(box);
row.appendChild(box);
binder.addBinding(box, "value", "tBean.someSetter");
...
private void setDefaultStyle(Doublebox box) {
box.setFormat("#.00");
box.setConstraint("no negative,no empty");
box.setWidth("50px");
String customJS = ""; //the JS above
//this is used to visually see that you're editing multiple cells at once
String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
box.setWidgetListener(Events.ON_CHANGE, customJS);
}
What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.

SDK2: checkboxes in a RallyGrid column?

I'd like to add a column with checkboxes in a rally grid (something like "Select Default"). It looks like that should be pretty simple using the 'checkcolumn' xtype. But that requires you to link in some additional extjs styles, and I'm not sure how to do that within the Rally extjs framework:
Extjs 4 checkcolumn not visible
Here's an example of such a column in ext-js: http://dev.sencha.com/deploy/ext-3.4.0/examples/grid/edit-grid.html
Is there a way do this with a Rally grid?
I ended up using a quick and dirty solution based on the anwser below:
{text: 'Default', dataIndex:'selected', align: 'center', width: 50, renderer: function(value, style, item, rowIndex) {
return "<input type='radio' name='primaryIndex' alt='"+ rowIndex + "' " + (value ? "checked='checked'" : "") + ">";
}},
AND:
checkRadioClick: function(event) {
var button = event.getTarget('input[type="radio"]');
if (button) {
...
Currently Ext's grid (which the Rally grid extends) doesn't support a checkbox column. The closest thing that comes out of the box is the Boolean column:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.grid.column.Boolean
This is because the grid expects you to have to click a cell to initiate an edit and a checkbox column is immediately editable without that action.
That given, I think you should be able to render a checkbox column by simply specifying a renderer for that column in your column config. It may be a little challenging to get the values back out of the grid when they change though since the values will not have been committed to the underlying records in the store (because no actual edit was triggered).
There is also a user submitted CheckColumn here that you may be able to use or at least as an example to get started:
http://docs.sencha.com/ext-js/4-1/source/CheckColumn.html#Ext-ux-CheckColumn
Maybe this is new with one of the newer preview versions? I did this:
Ext.create( 'Rally.ui.grid.Grid', {
selType: 'checkboxmodel',
selModel: {
injectCheckbox: 1,
mode: 'SIMPLE',
listeners: {
selectionchange: function( model, selected ) {
// do stuff
},
scope: this
}
}

Categories

Resources