SetRowData and DirtyCells - javascript

I'm using SetRowData to set some row data in a jqGrid
jqColModel = gJqGrid.jqGrid('getGridParam','colModel');
rowData = gJqGrid.jqGrid('getRowData', rowid);
for (var i=0; i<newData.length; i++){
rowData[jqColModel[i+1].name] = newData[i];
}
gJqGrid.jqGrid('setRowData', rowid, rowData);
This is working as expected. The jqGrid row is being updated with the values from the newData object.
I'm then trying to get all the modified cells using
jqRows = gJqGrid.jqGrid('getChangedCells', 'dirty');
but this doesn't seem to be working. I'm trying to batch up all the changes and create a custom save event
My grid definition is as below
$(gJqSel_Table).jqGrid({
caption : 'jqGrid'
, datatype : 'local'
, loadonce : true
, data : formattedLineData
, colNames : customColNames
, colModel : customColModel
, autoencode : true
, rowNum : 1000
, keys : true
, sortable : false
, hidegrid : false
, multiselect : false
, altRows : false
, height : '100%'
, autowidth : true
, shrinkToFit : true
, cellEdit : gSettings.editMode
, cellsubmit : 'clientArray'
, afterEditCell : function (rowid) {
var $editControl = $("#" + rowid).find("input, select, textarea");
if ($editControl){
$editControl.on('paste', function(e) {
GridPaste(e, rowid);
});
}
}
});
Can someone provide some guidance about how I can
use a JSON object to set all the cell values of a row
flag each cell in the row as dirty so that the getChangedCells method knows that the values have changed?

After more reading of the jqGrid documentation I found this
setRowData
Do not use this method when you are editing the row or cell. This will
set the content and overwrite the input elements.
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:methods
Changing my code to use the setCell method works
Cell value is updated
Cell is marked as dirty and included in the getChangedCells results
My code is as below
jqColModel = gJqGrid.jqGrid('getGridParam','colModel');
for (var i=0; i<newData.length; i++){
colName = jqColModel[i].name;
gJqGrid.jqGrid('setCell', rowid, colName, newData[i], 'dirty-cell');
}
Updated
As #Oleg pointed out in the comments, I also had to add the following to mark the jqGrid line as edited:
gJqGrid.setRowData(rowid, false, 'edited');

Related

Why subscribe event of dropdown is being called on load knockoutJs?

This may be a basic question but I am unable to get any solution.
I am trying to show a list of formats in a dropdown. I am using knockout binding to do so. I want to show a specific value initially.
When user selects some other value from the dropdown it should show the selected value (which is working fine).
On selecting any option I want to get the selected value so that I can send it to the server. I am using subscribefor that.
Below is my code:
var obj = this;
obj.formatArray = ko.observableArray([{'text' : "MM/DD/YYYY"},
{'text' : "MM-DD-YYYY"},
{'text' : "MM.DD.YYYY"},
{'text' : "DD/MM/YYYY"},
{'text' : "DD-MM-YYYY"},
{'text' : "DD.MM.YYYY"}]);
var format1 = 'DD-MM-YYYY';
obj.formatArrayDefault = ko.observable({text :format1});
obj.formatArrayDefault.subscribe(function(newValue){
alert("default value " + format1);
alert("new value in subscribe " + newValue.text);
});
ko.applyBindings(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select class="" data-bind="options:formatArray(),optionsText:'text',value:formatArrayDefault"></select>
You can run the above snippet and check, alert inside subscribe is coming on loading and changing the value to be displayed to the first value in the array.
Why subscribe is called on load and why the value is changed to first value?
What mistake I am doing?
If the question is duplicate can someone give link to the solution (I searched here but could not get any solution).
if you just want the value of the dropdown after any change.
just take a observable and set it as value it the drop down and initially it will be blank and in your subscribe function just add a line of comparision if the value of drop down is empty dont call the alert function.
var obj = this;
obj.formatArray = ko.observableArray([{'text' : "MM/DD/YYYY"},
{'text' : "MM-DD-YYYY"},
{'text' : "MM.DD.YYYY"},
{'text' : "DD/MM/YYYY"},
{'text' : "DD-MM-YYYY"},
{'text' : "DD.MM.YYYY"}]);
var format1 = 'DD-MM-YYYY';
obj.initialLoad = true;
obj.formatArrayDefault = ko.observable(format1);
obj.formatArrayDefault.subscribe(function(newValue){
if(obj.initialLoad) {
obj.initialLoad = false;
}
else {
alert("Hello");
}
});
ko.applyBindings(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select class="projectUserAccess workflowSetOptions" data-bind="options:formatArray(),optionsText:'text',value:formatArrayDefault"></select>
===EDIT===
$(document).ready(function(){
var model = {
selectedType: 2 //default Type
};
var viewModel = {
selectedType: ko.observable(model.selectedType)
, availableTypes: ko.observableArray([
{ Label: 'Type1', Code: 1 }
, { Label: 'Type2', Code: 2 }
, { Label: 'Type3', Code: 3 }
])
};
ko.applyBindings(viewModel, $("#content")[0]);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="content">
<select data-bind="value: selectedType, options: availableTypes, optionsText: 'Label', optionsValue: 'Code', optionsCaption: 'Please select...'"></select><br/>
You've selected Type: <span data-bind="text: selectedType"></span>
</div>
Your array contains plain objets. In javascript, object comparison works like this:
var obj1 = { a: 1 };
var obj2 = { a: 1 };
console.log(obj1 === obj2); // false
console.log(obj1 === obj1); // true
It checks the actual object instance that is referenced by a variable, not the way it looks. Many libraries contain a "deepEquals" function that you can use to check if two objects actually look similar, but knockout doesn't use such a mechanism.
So when you set your initial selection, its value might be similar to the object at formatArray()[0], but knockout won't be able to mach the two together. I.e.:
obj.formatArrayDefault() === obj.formatArray()[1]; // false
Now, when applying bindings, knockout tries to solve the mismatch between selection and source data. It can't find an <option> element to match with the selection that is passed to the value binding.
It has to render a selected option, so it defaults to the first one. This is when your initial object gets replaced by formatArray()[0] and the subscription is triggered.
Here's a solution: we put an actual reference to the first object in our initial value!
var obj = this;
obj.formatArray = ko.observableArray([{'text' : "MM/DD/YYYY"},
{'text' : "MM-DD-YYYY"},
{'text' : "MM.DD.YYYY"},
{'text' : "DD/MM/YYYY"},
{'text' : "DD-MM-YYYY"},
{'text' : "DD.MM.YYYY"}]);
var format1 = 'DD-MM-YYYY';
obj.formatArrayDefault = ko.observable(obj.formatArray()[1]);
obj.formatArrayDefault.subscribe(function(newValue){
console.log("default value " + format1);
console.log("new value in subscribe " + newValue.text);
});
ko.applyBindings(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select class="" data-bind="options:formatArray(),optionsText:'text',value:formatArrayDefault"></select>

jquery datables plugin and dynamic object name

I struggling with datatables to fill my table.
The problem i have is that when i get my google calendars in this format
{"23gjsd91su3guu509o1bchhqms#group.calendar.google.com":{"calendar_id":"23gjsd91su3guu509o1bchhqms#group.calendar.google.com","calendar_title":"#1612 White Quartz Apartment"},"vqbidsn2u4edlvto0frvevk6ig#group.calendar.google.com":{"calendar_id":"vqbidsn2u4edlvto0frvevk6ig#group.calendar.google.com","calendar_title":"#994 Cisco Amber (T2)"},"bi07i6futd90lvq9ba8ufvqdu8#group.calendar.google.com":{"calendar_id":"bi07i6futd90lvq9ba8ufvqdu8#group.calendar.google.com","calendar_title":"#1443. Marley Blue"}}
Need help on put datatables to work with this.
Thanks
You must sanitize the JSON so it is ordered on the form [{item}, {item}, ..] :
function sanitizeData() {
result = [];
Object.keys(data).forEach(function(key) {
result.push(data[key]);
})
return result;
}
Then, if you have table like this
<table id="example"></table>
You can now populate a dataTable with the content of the JSON this way :
var table = $('#example').DataTable({
data : sanitizeData(),
columns : [
{ title : 'id', data : 'calendar_id' },
{ title : 'title', data : 'calendar_title' }
]
})
demo -> http://jsfiddle.net/zbuudydv/1/

Replicate data into JQGrid

I am creating a jqgrid i m creating a row with 2 columns with dropdown box. The dropdowns are getting populated using ajax call. My requirement is I want to replicate this row on click on ADD button in UI. For example for now one row is coming into jqgrid, after clicking ADD button a new row with same content with out refreshing the changed value in first row should be displayed. Is there any way to do that? My jqgrid code is
$("#tbl").jqGrid('GridUnload');
$("#tbl").jqGrid(
{
url : "/searchCriteria.do",
datatype : 'json',
colModel :
[
{name : "test1",label : "TEST1", search : false,cellEdit:true, editable: true,edittype:"select",width:150 ,formatter: createDropDown,title:false},
{name : "test2",label : "TEST2", search : false,cellEdit:true, editable: true,edittype:"select",width:150 ,formatter: createDropDown,title:false}
],
viewrecords: true,
loadonce:true,
width: 1000,
multiselect : true
});
});
You can use a combination of the getLocalRow and addRowData methods to achieve your functionality. Docs for these methods.
Let's say in your HTML you have a button:
<button id="add" type="button">ADD</button>
In your javascript you could have:
<script>
$("#add").click(function(){
var id_of_new_row = something; //you haven't specified which are the exact rows you'd like selected.
//you could use the getDataIDs method to get the row-IDs you're looking for
var new_row_data = $("#gridId").jqGrid('getLocalRow', id_of_new_row));
$("#gridId").jqGrid('addRowData',id_of_new_row+1, new_row_data, "last");
});
</script>

JQgrid on sorting data changes for ID column

I am using JQgrid to display data, data in grid is added row by row. also i am using "local" data type to enable sorting on client side.
i am having 'id'in colmodel which stores database Id. at first time data is loaded properly
but when i click on header for sorting data content of 'id' column changes to 1,2 ...
please help..
my code
var pageNumber=0,
previouslySelectedId,
numberOfRecords;
var numberOfPages,sortingFlag=false;
$(function() {
$("#supplierCommodityList").jqGrid({
datatype: "local",
colNames:['ID','Supplier','Commodity','Unit','Cost Per Unit','Start Date','End Date'],
colModel:[
{name:'id',index:'id',hidden:true},
{name:'supplier.name',index:'supplier.name',sorttype:"string",formatter:wrapToLinkFormatter},
{name:'coProductSpecification.name',index:'coProductSpecification.name',sorttype:"string",sortable:true},
{name:'unit',index:'unit',sorttype:"string"},
{name:'expense',index:'expense',sorttype:"int"},
{name:'startDateStr',index:'startDate',formatter:dateFormatter},
{name:'endDateStr',index:'endDate',formatter:dateFormatter}
],
pager: '#supplierCommodityPager', //require id pagination, contains id for pagination div.
viewrecords: true,
multiselect: false, // to enable multiselect (chack box)
caption: "Supplier Commodity", //to show title on top
width: 920,
height:600,
viewrecords: true,
loadonce: true, // to enable sorting on client side
sortable: true, //to enable sorting
onPaging:paginationEvent, //pagination
onSortCol:sortingEvent,
gridComplete:gridCompleteFunction,
editurl: "clientArray"
}).navGrid('#supplierCommodityList',{edit:false,add:false,del:false});
attach_events(pagiantion_control_classes,'supplierCommodityList','supplierCommodityPager',get_supplier_commodity_details);
sortingEvent.gridId='supplierCommodityList'; //Id of grid
sortingEvent.pagerId='supplierCommodityPager';//Id of Pager
get_supplier_commodity_details(0);
});
/**
* method to get data .
*/
var get_supplier_commodity_details=function(requestedPage){
if(typeof requestedPage == 'undefined')
requestedPage=0;
var rurl='supplierCommodity/false';
$.ajax({
url: rurl+'/'+requestedPage,
processData:false,
type: 'GET',
success: function(data, textStatus, jqXHR){
render_supplier_commodity_details(data,requestedPage);
}
});
};
/**
* method used to render data in grid, row by row
*
*/
var render_supplier_commodity_details=function(data,pageNo){
numberOfRecords=data.numberOfRecords;
var numberOfPages=data.totalPages;
var noOfRecordPerPage=0;
console.debug(data);
$.each(data.supplierCommodityList,function(i,row){
$("#supplierCommodityList").jqGrid('addRowData',row.id,row);
noOfRecordPerPage+=1;
});
//alert(noOfRecordPerPage);
$("#supplierCommodityList").setGridParam({rowNum:numberOfRecords});
//jQuery("#supplierCommodityList").trigger("reloadGrid"); // to avoid total no of pages to be shown as 0.
$('span#sp_1_supplierCommodityPager').text(data.totalPages); //shows total pages
$('input.ui-pg-input').val(pageNo+1);
$("#supplierCommodityList").setGridParam({rowNum:numberOfRecords});
if(numberOfPages==1){
$('#supplierCommodityPager .ui-paging-info').text('View '+ 1 +' - '+ noOfRecordPerPage+ ' of '+noOfRecordPerPage);
}else if(numberOfPages==(parseInt(pageNo)+1)){
var minrecord=numberOfRecords-noOfRecordPerPage+1;
var maxrecord=numberOfRecords;
$('#supplierCommodityPager .ui-paging-info').text('View '+ minrecord +' - '+ maxrecord+ ' of '+numberOfRecords);
}else if(numberOfPages!=1){
var minrecord=(noOfRecordPerPage*pageNo)+1;
var maxrecord=noOfRecordPerPage*(pageNo+1)>numberOfRecords?noOfRecordPerPage :noOfRecordPerPage*(pageNo+1);
$('#supplierCommodityPager .ui-paging-info').text('View '+minrecord +' - '+ maxrecord+ ' of '+data.numberOfRecords);
}
};
/**
* method handling sorting of column
*/
sortingEvent=function(index,iCol,sortorder){//index=col. name, icol=index of column,sortorder=asc or desc
// console.debug(index+ iCol+sortorder+" satrt");
sortingFlag=true; //flag required in gridCompleteFunction to change Text in Pager.
numberOfPages=$('span#sp_1_'+sortingEvent.pagerId).text();
var pageNumber=$('#'+sortingEvent.pagerId+' .ui-pg-input').val();
if(iCol== 6 || iCol==7){
var obj=$("#"+sortingEvent.gridId).jqGrid('getRowData');
console.debug(obj);
compareDate.sortorder=sortorder=='asc'?1:-1; //for acending order directly return 1 if 1st element<2nd element
compareDate.sortingField=(iCol==6)?'startDateStr':'endDateStr';
obj.sort(compareDate);
console.debug(obj);
var gridObj = jQuery("#"+sortingEvent.gridId);
var textOnPager=$('#'+sortingEvent.pagerId+' .ui-paging-info').text();
gridObj.clearGridData();
$.each(obj,function(i,row){
$("#"+sortingEvent.gridId).jqGrid('addRowData',row.id,row); //appends data row by row to grid
});
$('#'+sortingEvent.pagerId+' .ui-paging-info').text(textOnPager);
$('span#sp_1_'+sortingEvent.pagerId).text(numberOfPages); //shows total pages
$('#'+sortingEvent.pagerId+' .ui-pg-input').val(pageNumber);
return 'stop';
}
};
/**
* method called when we click on link for updating Headline
*/
clickMethod=function(id){
if(id!=null && typeof id != 'undefined')
window.location = "/kiss/portal/yoadmintool/supplierCommodity/supplierCommodityDetail/"+id+"/";
else
window.location = "/kiss/portal/yoadmintool/supplierCommodityList";
};
/*
* method which gets called on pagination.
*/
var paginationEvent=function(pgButton){
pageNumber=$('#supplierCommodityPager .ui-pg-input').val();
var gridObj = jQuery("#supplierCommodityList");
gridObj.clearGridData();
get_supplier_commodity_details(pageNumber-1);
};
gridCompleteFunction=function(){
var noOfRecordPerPage=jQuery("#supplierCommodityList").jqGrid('getGridParam', 'records');
if(sortingFlag){
if(numberOfPages==1){
$('#supplierCommodityPager .ui-paging-info').text('View '+ 1 +' - '+ noOfRecordPerPage+ ' of '+noOfRecordPerPage);
}else if(numberOfPages==(parseInt(pageNumber)+1)){
var minrecord=numberOfRecords-noOfRecordPerPage+1;
var maxrecord=numberOfRecords;
$('#supplierCommodityPager .ui-paging-info').text('View '+ minrecord +' - '+ maxrecord+ ' of '+numberOfRecords);
}else if(numberOfPages==0){
}else if(numberOfPages!=1){
var minrecord=(noOfRecordPerPage*pageNumber)+1;
var maxrecord=noOfRecordPerPage*(parseInt(pageNumber))>numberOfRecords?noOfRecordPerPage :noOfRecordPerPage*(parseInt(pageNumber));
$('#supplierCommodityPager .ui-paging-info').text('View '+minrecord +' - '+ maxrecord+ ' of '+numberOfRecords);
}
}
sortingFlag=false;
$('.ui-state-disabled.ui-pg-button').removeClass('ui-state-disabled').addClass('ui-state-enabled');//to enable pager button
};
/**
* method to wrap discription to link for updation purpose
*/
wrapToLinkFormatter=function(cellvalue, options, rowObject){
var link=""+cellvalue+"";
return link;
};
I have seen the jsfiddle demo many times and I am wonder where is the origin of it. The problem is that the demo is really bad template. It contains many small errors and shows the worst way to fill jqGrid with local data. Please never use the template for your real code.
The error which is in your current code is the following: you choosed id as the name of the first column. The id property will be used to save the rowid (the id of <tr> elements of the grid). On the one side you use id: 48803 and id: 48769. On the other side you use $("#grid").jqGrid('addRowData', i + 1, mydata[i]);. So the id will be set to i + 1 (1 and 2). So the values 48803 and 48769 will be placed in the grid, but the id properties of internal data parameter will be overwritten to 1 and 2 values. If you would change the code to $("#grid").jqGrid('addRowData', data[i][0], mydata[i]); the problem will be solved.
Nevertheless I strictly recommend you to rewrite the code. You should first fill the mydata and then create the grid with data: mydata abd gridview: true options. You should additionally fix the sorttype to corresponds the data which you use. I recommend you additionally to use height: "auto" instead of height: 250 and include pager. The current code will just display first 20 rows of the data (rowNum has default value 20) and the user will be not able to see the next page.

Ext JS Search possibility in MultiSelect ComboBox

I want to know that how in ExtJS MultiSelect ComboBox i can search for a value. Like if i have entered 's' then a list of items starting with a must be displayed and the item selector should select if it matches with 's'.
This is the code i tried.....
cbCfg = {
name : property.columnname,
hideOnSelect : false,
triggerAction : 'all',
mode : 'local',
width : comboFieldSize,
store : new Ext.data.SimpleStore({
id : 0,
fields : ['strValue','strText'],
data : data
}),
listWidth : 400,
valueField : 'strValue',
displayField : 'strText'
};
field = new form.MultiCombo(cbCfg);
thnkz in advance,
just:-)
I assume that MultiSelect ComboBox extends functionality of Ext.form.ComboBox.
You could try going with triggerAction : 'query', which is the default - it should filter out non-matching entries. Although that could be a little bit counter-intuitive for the user.
Another possible approach is adding typeAhead : true property - should trigger suggesting suggestions based on the text entered by user.

Categories