MVC3 jquery.datatables.editable not picking up non visible id column - asp.net-mvc-3

I have a project where I want to inline edit a value in a table generated via DataTables and am therefore using dataTables.editable
The table is rendering fine but when I try and to sumit an edit I get an error and if I look at the return value the id field is blank.
The controller action is as follows:
public ActionResult AjaxHandler(jQueryDataTableParamModel param)
{
var allMonthlyCosts = _unitOfWork.MonthlyCostRepository.Get(includeProperties: "Period, Employee");
IEnumerable<MonthlyCost> filteredMonthlyCosts;
if (!string.IsNullOrEmpty(param.sSearch))
{
filteredMonthlyCosts = _unitOfWork.MonthlyCostRepository.Get(includeProperties: "Period, Employee")
.Where(mc => mc.Period.Name.Contains(param.sSearch)
||
mc.Employee.ClockNo.Contains(param.sSearch));
}
else
{
filteredMonthlyCosts = allMonthlyCosts;
}
var displayedMonthlyCosts = filteredMonthlyCosts
.Skip(param.iDisplayStart)
.Take(param.iDisplayLength);
var result = from mc in displayedMonthlyCosts
select new { ID = mc.Id, EvisionCost = mc.EvisionCost, EmployeeNo = mc.Employee.ClockNo, PeriodName = mc.Period.Name, TotalDays = mc.TotalDays, TotalCost = mc.TotalCost() };
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allMonthlyCosts.Count(),
iTotalDisplayRecords = filteredMonthlyCosts.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}
The Javascript is as follows:
$('#myDataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "MonthlyCost/AjaxHandler",
"bProcessing": true,
"aoColumns": [
{ "mData": "ID",
"bSearchable": false,
"bSortable": false,
"bVisible": false
},
{ "mData": "EvisionCost" },
{ "mData": "PeriodName" },
{ "mData": "EmployeeNo" },
{ "mData": "TotalDays" },
{ "mData": "TotalCost" }
]
}).makeEditable({
sUpdateURL: "/MonthlyCost/UpdateData",
"aoColumns": [
{},
null,
null,
null,
null]
});
The error I get is:
Cell cannot be #Updated(Server Error)
And the returned form is as follows:
value:2505
id:
rowId:0
columnPosition:0
columnId:1
columnName:EvisionCost

Issue is quite st.forward
Your editing is not reaching this plug-in code below . Thats why its throwing the error of your mention
CODE IN EDITABLE DATATABLE PLUGIN:
//Utility function used to apply editable plugin on table cells
function fnApplyEditable(aoNodes) {
var oDefaultEditableSettings = {
event: 'dblclick',
"callback": function (sValue, settings) {
properties.fnEndProcessingMode();
if (sNewCellValue == sValue) {
var aPos = oTable.fnGetPosition(this);
oTable.fnUpdate(sValue, aPos[0], aPos[2]);
} else {
var aPos = oTable.fnGetPosition(this);
oTable.fnUpdate(sOldValue, aPos[0], aPos[2]);
properties.fnShowError(sValue, "update");
}
},
"submitdata": function (value, settings) {
properties.fnStartProcessingMode();
sOldValue = value;
sNewCellValue = $("input,select", $(this)).val();
var id = fnGetCellID(this);
var rowId = oTable.fnGetPosition(this)[0];
var columnPosition = oTable.fnGetPosition(this)[1];
var columnId = oTable.fnGetPosition(this)[2];
var sColumnName = oTable.fnSettings().aoColumns[columnId].sName;
if (sColumnName == null || sColumnName == "")
sColumnName = oTable.fnSettings().aoColumns[columnId].sTitle;
return {
"id": id,
"rowId": rowId,
"columnPosition": columnPosition,
"columnId": columnId,
"columnName": sColumnName
};
},
"onerror": function () {
properties.fnEndProcessingMode();
properties.fnShowError("Cell cannot be updated(Server error)", "update");
},
"height": properties.height
};
This issue i am facing recently and i am trying like
<script type="text/javascript">
$(document).ready(function () {
$('#myDataTable').dataTable({ "bProcessing": true,
**"bServerSide": true,
"sAjaxSource": 'Home/AjaxHandler',
"sUpdateURL": '#Url.Action("UpdateData","Home")',
"sAddURL": '#Url.Action("AddData","Home")' ,
"sDeleteURL": '#Url.Action("DeleteData","Home")',**
"aoColumns": [
{ "sName": "ID",
"bSearchable": false,
"bSortable": false,
"bVisible": false
},
{ "sName": "Contact_Name" },
{ "sName": "Contact_Address" },
{ "sName": "Lead_Source" },
{ "sName": "Domain" },
]
}).makeEditable();
});
</script>
}
If this work please let me know . If you find any other way around do mention it . I am also in the same situation like you Finding answers
Regards

Related

getting error TypeError: a is undefined in datatable export custom function

I need to export all data in datatable, so for that i have added ajax call in action for the export button, when i click on export button it fire the ajax call and also getting all the data in the response but after that ajax call in console i am getting error TypeError: a is undefined, can anyone please help me to resolve this issue, here is my code for that
Jquery :
function cmpTable() {
var buttonCommon = {
exportOptions: {
format: {
body: function (data, row, column, node) {
if (column == '1' || column == '2' || column == '3') {
var data = data.replace(/(<([^>]+)>)/ig, "")
data = data.replace('$', '');
return data.replace('%', '');
} else {
var data = data.replace(/(<([^>]+)>)/ig, "")
return data;
}
}
}
}
};
var branch = $("#branch").val();
var soc_start_date = $("#soc_start_date").val();
var soc_end_date = $("#soc_end_date").val();
var ot_start_range = $("#ot_start_range").val();
var ot_end_range = $("#ot_end_range").val();
var ep_start_range = $("#ep_start_range").val();
var ep_end_range = $("#ep_end_range").val();
var st_start_range = $("#st_start_range").val();
var st_end_range = $("#st_end_range").val();
var hha_start_range = $("#hha_start_range").val();
var hha_end_range = $("#hha_end_range").val();
var total_start_range = $("#total_start_range").val();
var total_end_range = $("#total_end_range").val();
var msw_start_range = $("#msw_start_range").val();
var msw_end_range = $("#msw_end_range").val();
var sn_start_range = $("#sn_start_range").val();
var sn_end_range = $("#sn_end_range").val();
var icd_start_range = $("#icd_start_range").val();
var icd_end_range = $("#icd_end_range").val();
var pt_start_range = $("#pt_start_range").val();
var pt_end_range = $("#pt_end_range").val();
var ep_end_start_range = $("#ep_end_start_range").val();
var ep_end_end_range = $("#ep_end_end_range").val();
var random_episode = $("#random_episode").val();
var page_length = 10;
if (random_episode != '') {
page_length = random_episode;
}
$('#cmp_table2').DataTable({
dom: 'Bfrtip',
searching: false,
"pageLength": page_length,
"processing": true,
"serverSide": true,
"aaSorting": [[ 3, "asc" ], [ 4, "asc" ]],
"destroy":true,
'ajax': {
"url": '<?php echo site_url('adhoc/adhoc_data'); ?>',
"type": 'POST',
data: {
branch: branch,
soc_start_date:soc_start_date,
soc_end_date:soc_end_date,
ot_start_range:ot_start_range,
ot_end_range:ot_end_range,
ep_start_range:ep_start_range,
ep_end_range:ep_end_range,
st_start_range:st_start_range,st_end_range:st_end_range,
hha_start_range : hha_start_range,
hha_end_range:hha_end_range,total_start_range:total_start_range,
total_end_range:total_end_range,
msw_start_range:msw_start_range,msw_end_range:msw_end_range,
sn_start_range : sn_start_range,sn_end_range:sn_end_range,icd_start_range:icd_start_range,
icd_end_range:icd_end_range,pt_start_range:pt_start_range,pt_end_range:pt_end_range,
ep_end_start_range:ep_end_start_range,ep_end_end_range:ep_end_end_range,random_episode:random_episode
},
},
"columns": [
{ "data": "display_name"},
{ "data": "LastName"},
{ "data": "MRN"},
{ "data": "SOCDate"},
{ "data": "EpStart"},
{ "data": "EpEnd"},
{ "data": "ICD"},
{ "data": "PhyLastName"},
{ "data": "SNVisits"},
{ "data": "HHAVisits"},
{ "data": "MSWVisits"},
{ "data": "PTVisits"},
{ "data": "OTVisits"},
{ "data": "STVisits"},
{ "data": "TotVisits"},
],
buttons: [
$.extend(true, {}, buttonCommon, {
extend: 'excelHtml5',
className: 'start_class',
text: 'Export',
title: 'Target Starting Episodes',
action: function (e, dt, node, config) {
$.ajax({
url: '<?php echo site_url('adhoc/adhoc_data'); ?>',
method: 'POST',
data: {
branch: branch,
soc_start_date:soc_start_date,
soc_end_date:soc_end_date,
ot_start_range:ot_start_range,
ot_end_range:ot_end_range,
ep_start_range:ep_start_range,
ep_end_range:ep_end_range,
st_start_range:st_start_range,st_end_range:st_end_range,
hha_start_range : hha_start_range,
hha_end_range:hha_end_range,total_start_range:total_start_range,
total_end_range:total_end_range,
msw_start_range:msw_start_range,msw_end_range:msw_end_range,
sn_start_range : sn_start_range,sn_end_range:sn_end_range,icd_start_range:icd_start_range,
icd_end_range:icd_end_range,pt_start_range:pt_start_range,pt_end_range:pt_end_range,
ep_end_start_range:ep_end_start_range,ep_end_end_range:ep_end_end_range,random_episode:random_episode,
type : 'all'
}
}).then(function (ajaxReturnedData) {
dt.rows.add(ajaxReturnedData.data).draw();
$.fn.dataTable.ext.buttons.excelHtml5.action.call(this, e, dt, node, config);
});
}
}),
]
});
}
Controller Action :
if(is_use_azure()) {
$otherdb->select('tb_Branch.description as display_name,LastName,MRN,SOCDate,EpStart,EpEnd,ICD,PhyLastName,SNVisits,HHAVisits,MSWVisits,PTVisits,
OTVisits,STVisits,TotVisits');
$otherdb->from('tb_Episode, tb_Branch');
if ($is_random_episodes) {
$otherdb->order_by("RAND()");
} else {
$otherdb->order_by($column_name,$order_dir);
}
$otherdb->limit($limit,$offset);
if($where !='') {
$otherdb->where($where,NULL, FALSE);
}
if($branch !='') {
//$otherdb->where_in('BranchID',$_POST['branch'],false);
}
$episode_data = $otherdb->get();
$episode_data = $episode_data->result_array();
$otherdb->select('count(*) as total');
$otherdb->from('tb_Episode, tb_Branch');
if($where !='') {
$otherdb->where($where,NULL, FALSE);
}
if($branch !='') {
$otherdb->where_in('BranchID',$_POST['branch'],false);
}
$count_data = $otherdb->get();
//echo $otherdb->last_query(); die;
$count_data = $count_data->result_array();
} else {
$this->db->select('tb_Branch.description as display_name,LastName,MRN,SOCDate,EpStart,EpEnd,ICD,PhyLastName,SNVisits,HHAVisits,MSWVisits,PTVisits,
OTVisits,STVisits,TotVisits');
$this->db->from('tb_Episode, tb_Branch');
if ($is_random_episodes) {
$this->db->order_by("RAND()");
} else {
$this->db->order_by($column_name,$order_dir);
}
if(isset($_POST['type']) && $_POST['type'] == 'all') {
} else {
$this->db->limit($limit,$offset);
}
if($where !='') {
$this->db->where($where,NULL, FALSE);
}
if($branch !='') {
$this->db->where_in('BranchID',$_POST['branch']);
}
$episode_data = $this->db->get();
$episode_data = $episode_data->result_array();
$this->db->select('count(*) as total');
$this->db->from('tb_Episode, tb_Branch');
if($where !='') {
$this->db->where($where,NULL, FALSE);
}
if($branch !='') {
$this->db->where_in('BranchID',$branch);
}
$count_data = $this->db->get();
$count_data = $count_data->result_array();
}
$random_episode = $count_data[0]['total'];
if(isset($_POST['random_episode']) && (int)$_POST['random_episode'] && $_POST['random_episode'] != 0) {
$random_episode = $_POST['random_episode'];
}
$total_data = $random_episode;
if(isset($_POST['type']) && $_POST['type'] == 'all') {
echo json_encode(array('draw'=>$_POST['draw'],'recordsTotal'=>$total_data,'recordsFiltered'=>$total_data,'data'=>$episode_data));
} else {
echo json_encode(array('draw'=>$_POST['draw'],'recordsTotal'=>$total_data,'recordsFiltered'=>$total_data,'data'=>$episode_data));
}
die;

How should I create a Tree structure in Rally of defects with respect to user story

I am able to get tree structure for the user stories but want it same for defects also which are related to particular user story so that at a singe screen I can see both user stories and the related defects.
You may use features: [{ftype:'groupingsummary'}] of ExtJS to group defects by user stories and even summarize by some other field, in the code below by PlanEstimate. To group defects by user story Requirement attribute on defect is used, which points to the related story. In this example defects are filtered by Iteration.
Ext.define('CustomApp', {
extend: 'Rally.app.TimeboxScopedApp',
componentCls: 'app',
scopeType: 'iteration',
comboboxConfig: {
fieldLabel: 'Select Iteration:',
labelWidth: 100
},
onScopeChange: function() {
this.makeStore();
},
makeStore: function() {
var filter = Ext.create('Rally.data.wsapi.Filter', {
property: 'Requirement',
operator: '!=',
value: null
});
filter= filter.and(this.getContext().getTimeboxScope().getQueryFilter());
filter.toString();
Ext.create('Rally.data.wsapi.Store', {
model: 'Defect',
fetch: ['ObjectID', 'FormattedID', 'Name', 'State', 'Requirement', 'PlanEstimate'],
autoLoad: true,
filters: [filter],
listeners: {
load: this.onDataLoaded,
scope: this
}
});
},
onDataLoaded: function(store, records){
if (records.length === 0) {
this.notifyNoDefects();
}
else{
if (this.notifier) {
this.notifier.destroy();
}
var that = this;
var promises = [];
_.each(records, function(defect) {
promises.push(this.getStory(defect, this));
},this);
Deft.Promise.all(promises).then({
success: function(results) {
that.defects = results;
that.makeGrid();
}
});
}
},
getStory: function(defect, scope) {
var deferred = Ext.create('Deft.Deferred');
var that = scope;
var storyOid = defect.get('Requirement').ObjectID;
Rally.data.ModelFactory.getModel({
type: 'HierarchicalRequirement',
scope: this,
success: function(model, operation) {
fetch: ['FormattedID','ScheduleState'],
model.load(storyOid, {
scope: this,
success: function(record, operation) {
var storyScheduleState = record.get('ScheduleState');
var storyFid = record.get('FormattedID');
var defectRef = defect.get('_ref');
var defectOid = defect.get('ObjectID');
var defectFid = defect.get('FormattedID');
var defectPlanEstimate = defect.get('PlanEstimate');
var defectName = defect.get('Name');
var defectState = defect.get('State');
var story = defect.get('Requirement');
result = {
"_ref" : defectRef,
"ObjectID" : defectOid,
"FormattedID" : defectFid,
"Name" : defectName,
"PlanEstimate" : defectPlanEstimate,
"State" : defectState,
"Requirement" : story,
"StoryState" : storyScheduleState,
"StoryID" : storyFid
};
deferred.resolve(result);
}
});
}
});
return deferred;
},
makeGrid: function() {
var that = this;
if (this.grid) {
this.grid.destroy();
}
var gridStore = Ext.create('Rally.data.custom.Store', {
data: that.defects,
groupField: 'StoryID',
pageSize: 1000,
});
this.grid = Ext.create('Rally.ui.grid.Grid', {
itemId: 'defectGrid',
store: gridStore,
features: [{ftype:'groupingsummary'}],
minHeight: 500,
columnCfgs: [
{
text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'Name', dataIndex: 'Name',
},
{
text: 'State', dataIndex: 'State',
summaryRenderer: function() {
return "PlanEstimate Total";
}
},
{
text: 'PlanEstimate', dataIndex: 'PlanEstimate',
summaryType: 'sum'
},
{
text: 'Story', dataIndex: 'Story',
renderer: function(val, meta, record) {
return '' + record.get('Requirement').FormattedID + '';
}
},
{
text: 'Story Schedule State', dataIndex: 'StoryState',
}
]
});
this.add(this.grid);
this.grid.reconfigure(gridStore);
},
notifyNoDefects: function() {
if (this.grid) {
this.grid.destroy();
}
if (this.notifier) {
this.notifier.destroy();
}
this.notifier = Ext.create('Ext.Container',{
xtype: 'container',
itemId: 'notifyContainer',
html: "No Defects found matching selection."
});
this.add( this.notifier);
}
});

Show/Hide Columns in Boot grid when onclick - Externally

i couldn't hide a show/hide a boot grid column after onclick boot grid re-load.
The issue is it works when the page is loaded first time, but i couldn't make it work after click event. Any help is appreciated.
<th id="th_state" data-identifier="true" data-column-id="state" data-visible="false">State</th>
$('#filter_group').change(function () {
$("#employee_grid").bootgrid("reload")
$("#th_state").attr("data-visible", "true") ; // Not working....
});
$("#employee_grid").bootgrid({
ajax: true,
rowCount: [50, 100, 200, 300, 500],
columnSelection: true,
requestHandler: function (request) {
request.type = 'grid';
var citiesGroup = [];
$("#cities_group").find("option:selected").each(function (index, value) {
if ($(this).is(':selected')) {
citiesGroup.push({
state: $(this).parent().attr("label"),
city: $(this).val()
});
}
});
if (request.sort) {
request.sortBy = Object.keys(request.sort)[0];
request.sortOrder = request.sort[request.sortBy];
request.chartType = $("#chartType").val();
request.date_from = $("#date_from").val();
request.date_to = $("#date_to").val();
request.citiesGroup = citiesGroup ;
delete request.sort
}
return request;
},
responseHandler: function (response) {
$("#txt_total_connects").html(response);
return response;
},
post: function ()
{
/* To accumulate custom parameter with the request object */
return {
id: "b0df282a-0d67-40e5-8558-c9e93b7befed"
};
},
url: "response.php",
formatters: {
},
labels: {
noResults: "<b>No data found</b>",
all: "",
loading: '<b>Loading Please wait....</b>'
},
templates: {
search: "",
//header: "",
}
});

Handsontable: Updating a cell renderer at runtime

I'm using handsontable, and I want to change the background color of a cell if its value is edited and changed. I can do this easily if my data source is an array of arrays (see fiddle: http://jsfiddle.net/chiman24/3o2c3c7m/).
document.addEventListener("DOMContentLoaded", function() {
// Row Styles
var blank = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = '#ABAAAA'
};
var align = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.verticalAlign = 'middle';
td.style.fontWeight = 'bold';
};
var highlight1 = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = '#BDD7EE';
td.style.textAlign = 'right';
};
var changedBackgroundColor = '#cbd9e4';
var defaultBackgroundColor = 'white';
var hasChanged = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = changedBackgroundColor;
};
var noChange = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = defaultBackgroundColor;
};
var data = [
["1", "Hear us from heaven", "New Life Worship",
"Anderson, Jared", "something"
],
["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
"Still Believe"
]
],
dataCopy = [
["1", "Hear us from heaven", "New Life Worship",
"Anderson, Jared", "something"
],
["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
"Still Believe"
]
],
container = document.getElementById('example1'),
hot1;
//Table Row and Col Options
hot1 = new Handsontable(container, {
data: data,
fixedColumnsLeft: 1,
columnSorting: true,
colHeaders: ["id", "title", "artist", "author", "album"],
columns: [{
type: "text"
}, {
type: "text"
}, {
type: "text"
}, {
type: "text"
}, {
type: "text"
}]
});
hot1.addHook('afterChange', afterChange);
function afterChange(changes, source) {
if (source == 'edit' || source == 'autofill') {
$.each(changes, function(index, element) {
var change = element;
var rowIndex = change[0];
var columnIndex = change[1];
var oldValue = change[2];
var newValue = change[3];
var cellChange = {
'rowIndex': rowIndex,
'columnIndex': columnIndex
};
if (oldValue != newValue) {
var cellProperties = hot1.getCellMeta(
rowIndex, columnIndex);
if (newValue != dataCopy[rowIndex][
columnIndex
]) {
cellProperties.renderer = hasChanged;
} else { //data changed back to original value.
cellProperties.renderer = noChange;
}
hot1.render();
}
});
}
}
});
// noSideScroll class added to fix some containers while side scrolling the table
$(window).scroll(function() {
$('.noSideScroll').css({
'left': $(this).scrollLeft()
});
});
However, when using an array of objects, I can't get it to work. (see fiddle: http://jsfiddle.net/chiman24/24mpavga/).
var data = [{
"id": 1,
"title": "First Loved Me",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}, {
"id": 2,
"title": "One Thing Remains",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}],
dataCopy = [{
"id": 1,
"title": "First Loved Me",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}, {
"id": 2,
"title": "One Thing Remains",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}],
container = document.getElementById('example1'),
hot1;
//Table Row and Col Options
hot1 = new Handsontable(container, {
data: data,
fixedColumnsLeft: 1,
columnSorting: true,
colHeaders: ["id", "title", "artist", "author", "album"],
columns: [{
data: "id"
}, {
data: "title"
}, {
data: "artist"
}, {
data: "author"
}, {
data: "album"
}]
});
hot1.addHook('afterChange', afterChange);
function afterChange(changes, source) {
if (source == 'edit' || source == 'autofill') {
$.each(changes, function(index, element) {
var change = element;
var rowIndex = change[0];
var columnIndex = change[1];
var oldValue = change[2];
var newValue = change[3];
var cellChange = {
'rowIndex': rowIndex,
'columnIndex': columnIndex
};
if (oldValue != newValue) {
var cellProperties = hot1.getCellMeta(
rowIndex, columnIndex);
if (newValue != dataCopy[rowIndex][
columnIndex
]) {
cellProperties.renderer = hasChanged;
} else { //data changed back to original value.
cellProperties.renderer = noChange;
}
hot1.render();
}
});
}
}
Is there a way to accomplish this? I want to get it working using an array of objects because my data coming from the server will be in JSON format. I've scoured the handsontable documentation for a couple of days to no avail. Any help will be much appreciated. Thanks.
I got some help from the handsontable github forum.
Apparently, if the data source is an array of objects, then when calling "getCellMeta", instead of passing in a numerical column index, you have to pass in the column index as a property like this:
hot.getCellMeta(2, hot.propToCol(columnIndex));
Here's the updated demo
Other way to change background color of cell is use the Cell Option
...
if (oldValue != newValue){
aCell.push(
{ row: rowIndex,
col: hot.propToCol(columnIndex),
className: "cssWithBackgroundColor" });
hot.updateSettings({ cell: aCell });
}
If the user undo change you can
if ( source == 'UndoRedo.undo'){
aCell.pop();
hot.updateSettings({ cell: aCell });
}

jqGrid Retain Invalid Cell Value After EditRules Pop Up

#Oleg - I am new to jqGrid.I have three issues. Urgent help required.
I am using jqGrid 3.8, inline edit mode.
I want to retain the invalid cell values after the pop up for invalid cell.
Also I want to set the focus back to the invalid cell.
I have "add row" and filter tool bar feature in my jqGrid. I have used Oleg's solution in creating drop down for filter tool bar (posted in another jQuery thread).
**
- Problem:
** I am calling setSearchSelect from afterSaveCell, because I want to add new values in filter drop down every time I add or delete column.(Note: column is a textbox). But the filter tool bar isn't getting refreshed even if I use
var sgrid = $("#list")[0];
sgrid.triggerToolbar();
See the code below for setting the toolbar.
<script type="text/javascript">
var mydata = [
{id:"1", Name:"Miroslav Klose", Category:"sport", Subcategory:"football"},
{id:"2", Name:"Michael Schumacher", Category:"sport", Subcategory:"formula 1"},
{id:"3", Name:"Albert Einstein", Category:"science", Subcategory:"physics"},
{id:"4", Name:"Blaise Pascal", Category:"science", Subcategory:"mathematics"}
],
grid = $("#list"),
getUniqueNames = function(columnName) {
var texts = grid.jqGrid('getCol',columnName), uniqueTexts = [],
textsLength = texts.length, text, textsMap = {}, i;
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text !== undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
return uniqueTexts;
},
buildSearchSelect = function(uniqueNames) {
var values=":All";
$.each (uniqueNames, function() {
values += ";" + this + ":" + this;
});
return values;
},
setSearchSelect = function(columnName) {
grid.jqGrid('setColProp', columnName,
{
stype: 'select',
searchoptions: {
value:buildSearchSelect(getUniqueNames(columnName)),
sopt:['eq']
}
}
);
};
grid.jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name:'Name', index:'Name', width:200 ,editable:true},
{ name:'Category', index:'Category', width:200,editable:true },
{ name:'Subcategory', index:'Subcategory', width:200,editable:true }
],
sortname: 'Name',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
editurl: "clientArray",
multiselect: true,
pagination:true,
cellEdit: true,
cellsubmit: 'clientArray',
//ignoreCase: true,
pager: '#pager',
height: "auto",
enableSearch: true,
caption: "How to use filterToolbar better locally",
afterSaveCell: function(rowid,name,val,iRow,iCol) {
setSearchSelect(name);
jQuery("#list").('setColProp', name,
{
width:100
}
);
var sgrid = $("#list")[0];
sgrid.triggerToolbar();
alert(name);
},
loadComplete: function () {
setSearchSelect('Category');
}
}).jqGrid('navGrid','#pager',
{edit:false, add:false, del:false, search:false, refresh:true});
setSearchSelect('Category');
setSearchSelect('Subcategory');
grid.jqGrid('setColProp', 'Name',
{
searchoptions: {
sopt:['cn'],
dataInit: function(elem) {
$(elem).autocomplete({
source:getUniqueNames('Name'),
delay:0,
minLength:0
});
}
}
});
grid.jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:"cn"});
function addRow(tableId){
var loopRow = document.getElementById("addRowsInput").value;
var recordCount = '';
var rwData = '';
//var selRowIds = getRowIDs('list');
var gridProducts = $("#list");
var resetFirstRow = jQuery("#list").getRowData( 1 );
jQuery("#list").setRowData( 1, resetFirstRow );
if(loopRow == null || loopRow == "" || loopRow == "Enter number of units to be added")
{
loopRow = 1;
}
for(i=0; i< loopRow; i++)
{
recordCount = jQuery("#list").getGridParam("records") ;
var emptydata = [
{id:(recordCount+1), Name:"", Category:"", Subcategory:""}]
gridProducts.jqGrid('addRowData', recordCount+1, emptydata[0]);
}
}
</script>
#Oleg - one more question on the solution you suggested. Sorry I tried myself to find it but couldn't.
In the buildSearchSelect: method , how can I include filter for empty string.
As explained above I have a "Add Row" button. So when the user wants to filter rows with empty columns I need a filter value.
The implementation of setSearchSelect function from my old answer work only if the searching toolbar not yet exist. If the toolbar exist one have to modify the options of the select element or autocomplete source of the jQuery UI autocomplete widget.
I extended the code. You can see the new version of the demo here. In the same way one could use inline editing instead of the cell editing.
Here is the modified JavaScript code:
var mydata = [
{id:"1", Name:"Miroslav Klose", Category:"sport", Subcategory:"football"},
{id:"2", Name:"Michael Schumacher", Category:"sport", Subcategory:"formula 1"},
{id:"3", Name:"Albert Einstein", Category:"science", Subcategory:"physics"},
{id:"4", Name:"Blaise Pascal", Category:"science", Subcategory:"mathematics"}
],
grid = $("#list"),
getUniqueNames = function(columnName) {
var texts = grid.jqGrid('getCol',columnName), uniqueTexts = [],
textsLength = texts.length, text, textsMap = {}, i;
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text !== undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
uniqueTexts.sort();
return uniqueTexts;
},
buildSearchSelect = function(uniqueNames) {
var values=":All";
$.each (uniqueNames, function() {
values += ";" + this + ":" + this;
});
return values;
},
setSearchSelect = function(columnName) {
var $select = $('select#gs_'+columnName), un = getUniqueNames(columnName),
htmlForSelect = '<option value="">All</option>', i, l=un.length, val;
grid.jqGrid('setColProp', columnName,
{
stype: 'select',
searchoptions: {
value:buildSearchSelect(un),
sopt:['eq']
}
}
);
if ($select.length > 0) {
// The searching toolbar already exist. One have to update it manually
for (i=0;i<l;i++) {
val = un[i];
htmlForSelect += '<option value="'+val+'">'+val+'</option>';
}
$select.html(htmlForSelect);
}
},
setAutocomplete = function(columnName) {
var $input = $('input#gs_'+columnName), un = getUniqueNames(columnName);
grid.jqGrid('setColProp', columnName,
{
searchoptions: {
sopt:['cn'],
dataInit: function(elem) {
$(elem).autocomplete({
source:un,
delay:0,
minLength:0
});
}
}
});
if ($input.length > 0) {
// The searching toolbar already exist. One have to update the source
$input.autocomplete('option', 'source', un);
}
},
selectColumns = ['Category','Subcategory'], autocompleteColumns = ['Name'];
grid.jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name:'Name', index:'Name', width:200 ,editable:true},
{ name:'Category', index:'Category', width:200,editable:true },
{ name:'Subcategory', index:'Subcategory', width:200,editable:true }
],
sortname: 'Name',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
cellEdit: true,
cellsubmit: 'clientArray',
ignoreCase: true,
pager: '#pager',
height: "auto",
caption: "How to use filterToolbar better locally including local cell editing",
afterSaveCell: function(rowid,name,val,iRow,iCol) {
if ($.inArray(name,selectColumns) !== -1) {
setSearchSelect(name);
} else if ($.inArray(name,autocompleteColumns) !== -1) {
setAutocomplete(name);
}
}
}).jqGrid('navGrid','#pager',
{edit:false, add:false, del:false, search:false, refresh:true});
$.each(selectColumns,function() {
setSearchSelect(String(this));
});
$.each(autocompleteColumns,function() {
setAutocomplete(String(this));
});
grid.jqGrid('filterToolbar',
{stringResult:true, searchOnEnter:true, defaultSearch:"cn"});

Resources