Disable Cell Editing or Make Cell Readonly - handsontable

When the user types a value in a cell of a certain column, I would like to make the cell of the next column(same row), readonly ou not editable. If the user deletes de value, I would like to make the next cell editable again.
Can someone give an example of how to achive this?
Thank you.

You can try to define your columns like this:
const hot = new Handsontable(el, {
data: someData,
columns: [
{ type: 'text'},
{ type: 'numeric'},
{ type: 'text'}
]
});
You can update the settings like this
hot.updateSettings({
columns: [
{ type: 'text'},
{ type: 'text', readOnly: true},
{ type: 'text'}
]
});

Related

Kendo Grid calls 'create' operation instead of 'update' after adding new record

I've setup a basic Kendo Grid and I'm using the DataSourceResult class from the PHP Wrapper library on the sever side.
I've come across a strange issue... if I create a new record and then edit it (without refreshing the page), the create operation is called again, rather than the update operation.
If the page is refreshed after adding the new record, the update operation is called correctly after making changes to the record.
I can confirm that the DataSourceResult class is returning the correct data after the create operation, including the id of the new record.
Any ideas why this is happening (and how to stop it)?
Thanks
Update: Here's the datasource code. The query string in the url is just to easily distinguish the requests in Chrome's console. The additional data passed with each request is used by ajax.php to distinguish the different actions requested.
data = new kendo.data.DataSource({
transport: {
create: {
url: '/ajax.php?r=gridCreate',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'create' }
},
read: {
url: '/ajax.php?request=gridRead',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'read' }
},
update: {
url: '/ajax.php?r=gridUpdate',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'update' }
},
destroy: {
url: '/ajax.php?r=gridDestroy',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'destroy' }
},
parameterMap: function(data, operation) {
if (operation != "read"){
data.expires = moment(data.expires).format('YYYY-MM-DD HH:mm');
}
return data;
}
},
schema: {
data: 'data',
total: 'total',
model: {
id: 'id',
fields: {
id: { editable: false, nullable: true },
code: { type: 'string' },
expires: { type: 'date' },
enabled: { type: 'boolean', defaultValue: true }
}
}
},
pageSize: 30,
serverPaging: true,
serverSorting: true,
serverFiltering: true
});
Best solution
Set to update, create or delete different Call Action
From Telerik Support :
I already replied to your question in the support thread that you
submitted on the same subject. For convenience I will paste my reply
on the forum as well.
This problem occurs because your model does not have an ID. The model
ID is essential for editing functionality and should not be ommited -
each dataSource records should have unique ID, records with empty ID
field are considered as new and are submitted through the "create"
transport.
schema: {
model: {
//id? model must have an unique ID field
fields: {
FirstName: { editable: false},
DOB: { type: "date"},
Created: {type: "date" },
Updated: {type: "date" },
}
} },
For more information on the subject, please check the following
resources:
http://docs.kendoui.com/api/framework/model#methods-Model.define
http://www.kendoui.com/forums/ui/grid/request-for-support-on-editable-grid.aspx#228oGIheFkGD4v0SkV8Fzw
MasterLink
I hope this information will help
I have also the same problem & I have tried this & it will work.
.Events(events => events.RequestEnd("onRequestEnd"))
And in this function use belowe:
function onRequestEnd(e) {
var tmp = e.type;
if (tmp == "create") {
//RequestEnd event handler code
alert("Created succesully");
var dataSource = this;
dataSource.read();
}
else if (tmp == "update") {
alert("Updated succesully");
}
}
Try to Use this code in onRequestEnd event of grid
var dataSource = this;
dataSource.read();
Hope that it will help you.
Pass the auto-incremented id of the table when you call the get_data() method to display data into kendo grid, so that when you click on the delete button then Deledata() will call definitely.
Another variation, in my case, I had specified a defaultValue on my key field:
schema: $.extend(true, {}, kendo.data.transports["aspnetmvc-ajax"], {
data: "Data",
total: "Total",
errors: "Errors",
model: kendo.data.Model.define({
id: "AchScheduleID",
fields: {
AchScheduleID: { type: "number", editable: true, defaultValue: 2 },
LineOfBusinessID: { type: "number", editable: true },
Not sure what I was thinking but it caused the same symptom.

kendo grid delete command not working

i have developed a web application using kendo ui tools and theres a kendo grid with batch edit mode..
but when i press the delete button for any record in kendo grid it will erase from the list in grid but actually not in the data source.when i reload the page or grid the deleted item will still exist..
here is the code of my grid
<div id="grid">
</div>
<script type="text/javascript">
$("#submitMarketUser").click(function () {
var grid = $("#grid").data("kendoGrid");
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "WholeSaleTrade/GetTradeProductDetail",
dataType: "json",
data: {
test: $("#Names").val()
}
},
destroy: {
url: "WholeSaleTrade/DeletePro",
type: "POST",
dataType: "jsonp",
data: {
DAKy: $("#Names").val(),
DIKy: $("#btntxt").val()
}
},
create: {
url: "WholeSaleTrade/CreateProduct",
type: "POST",
dataType: "jsonp",
data: {
AKy: $("#Names").val(),
IKy: $("#btntxt").val()
}
}
},
pageSize: 5,
schema: {
model: {
id: "ProductKey",
fields: {
ProductKey: { editable: false, nullable: true },
ProductName: { validation: { required: true} }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
editable: true,
toolbar: ["create", "save"],
autobind: true,
pageable: true,
columns: [
{ field: "ProductName", title: "Product Name",
editor: function (container, options) {
var model = options.model;
$('<input id="btntxt" name="' + options.field + '"/>').appendTo(container).kendoComboBox({
dataSource: {
type: "POST",
transport: {
read: {
url: "MarketInformation/PopulateProducts",
success: function (data) {
var prod = data[0];
model.set("ProductName", prod.ItmNm);
model.set("ItmKy", prod.ItmKy);
model.set("UserKey", $("#Names").val());
}
}
}
},
dataValueField: "ItmKy",
dataTextField: "ItmNm"
});
}
},
{ command: ["destroy"], title: " " }
]
});
});
</script>
can not identify that where is the fault going and can somebody please help me to solve this matter.
There are three common reasons delete won't work:
1. Not setting editable of grid to inline or popup. The deleted items will be automatically processed through transport destroy only for "inline"/"popup" edit modes. Ex:
editable: {
mode: "inline",
}
//or
editable: "inline"
2. If on your datasource, you have the batch flag set to true, this means the datasource will make the call only after you tell it to, e.g calling sync(). Ex:
var dataSource = new kendo.data.DataSource({
batch: true,
//.....
});
//... in some where e.g in a save button click event call the following line:
dataSource.sync();
3. You should define id to your primary key of database field name inside model of datasource. Ex:
model: {
id: "ProductID",
fields: {
ProductID: { editable: false, nullable: true },
}
}
So the problem with your code is first one, i.e you did not set editable to inline or popup
If you choose not to include editable.mode in order to utilize the in-cell editing, you can set the toolbar of the grid to include the option save:
$("#grid").kendoGrid({
dataSource: {
transport: {
....
},
schema: {
....
}
},
toolbar: ["create", "save", "cancel"],
columns: [
....
],
editable: true
});
This will create a save button at the toolbar of the grid. After deleting any records by clicking the destroy command button, click on the save button to have the grid to make an Ajax call to the server to delete the record.
If you would rather delete the record automatically without including the save button, you could add a change event handler to the datasource of the grid:
$("#grid").kendoGrid({
dataSource: {
transport: {
....
},
schema: {
....
},
change: function(e) {
if (e.action === "remove") {
this.sync();
}
}
},
columns: [
....
],
editable: true
});
This will automatically sync the changes you made to the grid with the server when there's a data change.
Hmm try not including type: "POST", and see if it now works since as far as I can see that bit isn't included on the demo's and I don't think I included it when I last did inline edits/deletes.
I had put an arbitray name for an int on the server Delete Method.
[HttpPost]
public ActionResult DeleteRandomTest(Int32 randomTestId)
{
...
}
The default modelbinder was probably looking for a property called Id (same as the primary key of my type according to the configuration of the model).
.Model(config => config.Id(p => p.Id))
In fact, I proved this by changing the signature to the following:
[HttpPost]
public ActionResult DeleteRandomTest(Int32 Id)
{
...
}
My break point was hit after that.
Ultimately, I used the full type as the parameter as shown in the Kendo examples because I didn't want to have poorly named parameter names (not camel case) in the action. Shown as follows:
[HttpPost]
public ActionResult DeleteRandomTest([DataSourceRequest]
DataSourceRequest request, RandomDrugTest randomDrugTest)
{
...
}
This seems to the be the reason it wasn't working.
I had the same issue. My issue was caused by having a data property in the kendo model. Example:
{id: 1, data: ""}

jqGrid filter toolbar show search operator selector just for single column

I have jqGrid table with many columns. Searching in grid is made using filter toolbar. For most of them search is just simple default operator. For one datetime column I want different kind of operators and datepicker selector.
I have added dataInit datepicker initialization to searchoptions, necessary operators to searchoptions.sopt. To show this operators I have set searchOperators to true. So for this column all is ok. I have datepicker with operator selector popup. But for all other columns default operator icon is shown on the left of it. It is annoying as operator is default and user couldn't change it. So is there is some possibility to hide them using jqGrid API? As far as I could see I could hide this only using my custom code:
I need to check my column model and after rendering of grid (may be in loadComplete) for all columns that have empty sopt or sopt.length == 0 to remove operator selector. Or add CSS class that hide it. Not sure which of these solution is better (hide or remove) because removing could broke some logic, and hiding could affect width calculation. Here is sample of what I mean on fiddle
function fixSearchOperators()
{
var columns = jQuery("#grid").jqGrid ('getGridParam', 'colModel');
var gridContainer = $("#grid").parents(".ui-jqgrid");
var filterToolbar = $("tr.ui-search-toolbar", gridContainer);
filterToolbar.find("th").each(function()
{
var index = $(this).index();
if(!(columns[index].searchoptions &&
columns[index].searchoptions.sopt &&
columns[index].searchoptions.sopt.length>1))
{
$(this).find(".ui-search-oper").hide();
}
});
}
Does anybody have some better ideas?
I find the idea to define visibility of searching operations in every column very good idea. +1 from me.
I would only suggest you to change a little the criteria for choosing which columns of searching toolbar will get the searching operations. It seems to me more native to include some new property inside of searchoptions. So that you can write something like
searchoptions: {
searchOperators: true,
sopt: ["gt", "eq"],
dataInit: function(elem) {
$(elem).datepicker();
}
}
I think that some columns, like the columns with stype: "select", could still need to have sopt (at least sopt: ["eq"]), but one don't want to see search operators for such columns. Specifying of visibility of searching operations on the column level would be very practical in such cases.
The modified fiddle demo you can find here. I included in the demo CSS from the fix (see the answer and the corresponding bug report). The full code is below
var dataArr = [
{id:1, name: 'steven', surname: "sanderson", startdate:'06/30/2013'},
{id:2, name: "valery", surname: "vitko", startdate: '07/27/2013'},
{id:3, name: "John", surname: "Smith", startdate: '12/30/2012'}];
function fixSearchOperators() {
var $grid = $("#grid"),
columns = $grid.jqGrid ('getGridParam', 'colModel'),
filterToolbar = $($grid[0].grid.hDiv).find("tr.ui-search-toolbar");
filterToolbar.find("th").each(function(index) {
var $searchOper = $(this).find(".ui-search-oper");
if (!(columns[index].searchoptions && columns[index].searchoptions.searchOperators)) {
$searchOper.hide();
}
});
}
$("#grid").jqGrid({
data: dataArr,
datatype: "local",
gridview: true,
height: 'auto',
hoverrows: false,
colModel: [
{ name: 'id', width: 60, sorttype: "int"},
{ name: 'name', width: 70},
{ name: 'surname', width: 100},
{ name: 'startdate', sorttype: "date", width: 90,
searchoptions: {
searchOperators: true,
sopt: ['gt', 'eq'],
dataInit: function(elem) {
$(elem).datepicker();
}
},
formatoptions: {
srcformat:'m/d/Y',
newformat:'m/d/Y'
}
}
]
});
$("#grid").jqGrid('filterToolbar', {
searchOnEnter: false,
ignoreCase: true,
searchOperators: true
});
fixSearchOperators();
It displays the same result like youth:

ExtJS 4 rendering new grid based on a combobox selection

I have a grid which uses a remote store and remote pagination because I have too many records.The store for the main grid is:
Ext.define('ArD.store.RecordsListStore', {
extend: 'Ext.data.Store',
model: 'ArD.model.RecordsListModel',
autoLoad: true,
autoSync: true,
remoteSort: true,
remoteFilter: true,
pageSize: 15,
proxy: {
type: 'ajax',
actionMethods: 'POST',
api: {
read: g_settings.baseUrl + 'index.php/recordslist/getAll',
destroy: g_settings.baseUrl + 'index.php/recordslist/deleteRecord'
},
reader: {
type: 'json',
root: 'data',
totalProperty: 'totalCount',
successProperty: 'success'
},
writer: {
root: 'data',
writeAllFields: true,
encode: true
}
}
});
then I populate my grid and and it's all fine. But the problem is that I have a combobox which looks like this:
{
xtype: 'combo',
id: 'records_list_form_id',
emptyText: 'Choose Form',
editable: false,
store: 'FilterRecordsByForm',
displayField: 'title',
valueField: 'id',
lastQuery: '',
triggerAction: 'all',
queryMode: 'remote',
typeAhead: false,
width: 200,
listeners: {
select: this._filterRecords
}
}
And when I select something from the combobox there's the function :
_filterRecords: function()
{
var recStore = Ext.getStore('RecordsListStore');
var a = Ext.getCmp('records_list_form_id').getValue( );
var rec = Ext.getStore('FilterRecordsByForm').getAt(a);
console.log(recStore);
},
mostly just trying some things but I can get the ID of the selected element from the combobox and that is where I am.
What I need is having the id to make a new query usign my AJAX api (PHP/SQL backend) and populate the grid with the info related with this id. In my case I have 1:M relations so when I pass the Id i expect M records which I want to render on the place of the old grid.
Thanks
Leron
Use filter() method. Provide information that you need to filter by and store object will automatically request updated info from the server (you already have remoteFilter configured).
Look at Ext.Ajax() to make an on-demand ajax call to the server-side to load up your data and then use Store.loadData() or something like that to re-populate the Grid.

Endless loading of an ajax store with 2 comboboxes

I have two instances of the class AddressPanel on the panel.
Ext.define('AddressPanel', {
extend: 'Ext.tab.Panel',
initComponent: function() {
this.items = [
{
title: 'Stations',
itemId : 'pointStation',
closable: false,
items:[
{
xtype: 'combo',
fieldLabel: 'station',
store: stationStore,
queryMode: 'remote',
displayField: 'name',
valueField: 'id',
editable : false
}
Both of them contain comboboxes that are associated with the same very basic store
var stationStore = Ext.create('Ext.data.Store', {
fields: ['id', 'name'],
proxy: {
type: 'ajax',
url : '/address/stationname'
}
});
I can open the combo from the first instance and choose a station.
Then I can open the combo from the second instance and choose another station.
It works fine.
But when I open the combobox from the first instance of AddressPanel again I get an endless loading.
How can I fix it?
Thank you in advance.
You could add an id to your combobox and when you go from the first instance to the second you can reset your combobox with
Ext.getCmp('id').reset();
I made two copies of the store and set the store config of the the first combo to the first copy of the store and the store config of the second combo to the second copy.
It helps.

Resources