I have a web application, where I use a third party grid. The grid handles events on its cell in setCellValue, like this:
$("#productsGridContainer").dxDataGrid({
dataSource: data,
keyExpr: "Id",
allowColumnResizing: true,
showRowLines: true,
showBorders: true,
rowAlternationEnabled: true,
sorting: true,
paging: {
pageSize: 10
},
pager: {
showPageSizeSelector: true,
allowedPageSizes: [10, 20, 50, 100]
},
editing: {
mode: "row",
allowUpdating: true,
allowDeleting: true,
allowAdding: true
},
columns: [
{
dataField: "ItemDesc",
caption: "Description",
validationRules: [{ type: "required" }]
},
{
dataField: "ItemId",
caption: "SKU",
lookup: {
dataSource: skus,
displayExpr: "Value",
valueExpr: "Key"
},
setCellValue: function(newData, value, currentRowData) {
newData.ItemId = value;
$.ajax({
type: "POST",
url: rootDir + "PaaSubmission/GetSkuItemData",
data: '{ itemId: ' + value + ', custNo: ' + selectedCustomer.val() + ' }',
contentType: "application/json; charset=utf-8",
async: false, // if default/true, newData will not be defined in .done
dataType: "json"
})
.done(function(data) {
newData.ItemDesc = data.Description;
newData.ItemSize = data.Size;
newData.ItemOldPrice = data.OldPrice;
})
.fail(function(xhr, status, error) {
displayError("The ajax call to GetSkuItemData() action method failed:",
JSON.parse(xhr.responseText), "Please see the system administrator.");
})
}
As you can see, when the ajax call is done, it is too late to set newData properties. newData is still defined, but it is too late to set it, as setCellValue() is executed by then. THIS MAKES MY QUESTION DIFFERENT from other similar ones. Thus I have to call $ajax() synchronously using async: false. But I know that it is deprecated, as it freezes the browser. Could you please give me an advise on how it can be done without calling $ajax() synchronously?
Related
I am trying to populate one of the columns using select box in jqgrid. Below is the code.
$(document).ready(function(){
$("#grid").jqGrid({
url: "./info",
datatype: "json",
mtype: "GET",
ajaxSelectOptions:{
type: "GET",
dataType: "json",
success: function (result) {
console.log(result);
}
},
colNames: ["DeptId", "DeptName", "StuId", "StuName", "StuDoj"],
colModel: [
{ name: "deptId", hidden:true },
{ name:"deptName", width:90, editable:true, edittype:'select', formatter:'select', editoptions:{
dataUrl:'./getDepts',
buildSelect: function(res){
console.log(res);
var s='<select id="dept" name="dept">'
$.each(res,function(idx,obj){
$('#dept')
.append($('<option>', { value : obj.deptId })
.text(obj.deptName));
});
return s+"</select>";
}
}},
{ name: "studentId", hidden:true },
{ name: "studentName", width: 80,editable:true },
{ name: "studentDoj",width: 90,editable:true }
],
pager: "#pager",
rowNum: 5,
rowList: [5, 10, 20],
sortname: "empId",
sortorder: "asc",
sortable:true,
viewrecords: true,
gridview: true,
caption: "MyGrid",
jsonReader: {
repeatitems: false,
id: "empId",
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
}
});
$("#grid").jqGrid('navGrid','#pager',{add:false,view:true,search:true});
})
In the editOptions for colModel 'deptName' the dataUrl is not called to populate the select box. The jqgrid is populated using /info resturl which fetches the deptName for a particular student. I want the deptName to be of type select box and its value should be same as deptName fetched using info rest url
It should be called, but your data will be newer filled, since you overwrite the success function in ajaxSelectOptions.
In order to get response, please comment the success function or remove it
$("#grid").jqGrid({
url: "./info",
datatype: "json",
mtype: "GET",
ajaxSelectOptions:{
type: "GET",
dataType: "json"
},
....
});
UPDATE: With small changes your code is working fine. Here is a link to your code
Note that the formatter does not have option dataUrl. It is only available in in editing.
I have a mix of Select2JS and Datatables and here is the code involved in the issue:
$(function() {
var form_id = $('#form_id'),
form_results = $('#form_results');
form_results.DataTable();
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'json',
url: '/ajax/forms/get/',
data: JSON.stringify({
form_id: null,
show_archived: !!$('#show_archived').is(':checked'),
get_first: false,
format: 'select2',
}),
cache: false,
success: function(data) {
form_id.removeAttr('disabled');
form_id.select2({
data: data,
closeOnSelect: true,
matcher,
sorter,
}).on('select2:select', function(e) {
var selected_element = $(e.currentTarget);
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'json',
url: '/ajax/manage_forms/getFormData/',
data: JSON.stringify({
form_id: selected_element.val(),
get_first: true,
}),
cache: false,
success: function(response) {
form_results.DataTable({
data: response.data,
retrieve: true,
stateSave: true,
responsive: true,
columnDefs: [
{
className: 'select-checkbox',
orderable: false,
searchable: false,
targets: 0,
},
],
select: {
style: 'multiple',
selector: 'td:first-child',
},
});
},
error: function(xhr, ajaxOptions, thrownError) {
console.error(xhr.responseText);
},
});
});
},
error: function(xhr, ajaxOptions, thrownError) {
console.error(xhr.responseText);
},
});
});
On the PHP side there is a function building the data and send it back to the browser:
public function getFormData()
{
$inputJSON = file_get_contents('php://input');
$outputJSON = json_decode($inputJSON, true);
$arguments = array(
'Id' => $outputJSON['form_id'],
'FormName' => null,
'FormFileName' => null,
'FormTypeId' => 1
);
$form = $this->forms_model->get($arguments, $outputJSON['get_first'], self::$folders);
$result[] = array(
'',
'DT_RowId' => $form->Id,
$form->FormName,
$form->FaxNumber,
end(explode('/', $form->form_filepath))
);
return $this->output->set_content_type('application/json')->set_output(json_encode(array('data' => $result)));
}
The result from the above function looks like:
{
"data" : [
{
"0" : "",
"DT_RowId" : 3387,
"1" : "form",
"2" : "8772399284",
"3" : "form1.pdf"
}
]
}
For some reason the table is showing all the time "No data available in table" and I can't find where is the issue, can any find out what is wrong in my code?
I have spent the last two hours trying to figure this out but I can't.
Updates:
#charlietfl: the following didn't work at first complaining about the k not being defined so I modified a little bit however it didn't do the trick
response.data.map(function(k, o) {
return Object.keys(k).map(function(k) { return o[k];});
});
#CFP Support: your solution is not working either for some reason the table doesn't get updated with data.
In both cases I am not getting any Javascript error or nothing weird in the console it just does not work.
You need to add the "columns" and define them.
...stuff...
columnDefs: [
{
className: 'select-checkbox',
orderable: false,
searchable: false,
targets: 0,
},
],
columns: [
{data: "0"},
{data: "DT_RowId"},
{data: "1"},
{data: "2"},
{data: "3"}
], ....etc...
This tells the table what column to match with the incoming data (so you will need a table with 5 columns in the HTML - or build it with JS {not sure what you are using, but if you need help...}
This should get you past the immediate issue though.
EDIT: JSFiddle - https://jsfiddle.net/CFPSupport/5utwh4v3/6/
EDIT2: I see the issue - you are initializing then wanting to put more data.... OK.....
You should get the data IN the datatable init, not init+AJAX.... https://datatables.net/reference/option/ajax
I am trying to implement toolbar filtering using jqgrid v4.6 but I'm not able to filter the results
$('form[name="viewComplaintsForm"] button').click(function(e){
e.preventDefault();
var viewForm=$(this).parent('form');
complaintDeptId=viewForm.find('select option:selected').val();
complaintDeptName=viewForm.find('select option:selected').text();
if(complaintDeptId !=0){
var reqData={"complaintDeptId":complaintDeptId};
if (complaintList.is(':empty')){
complaintList.jqGrid({
url: "./getComplaintDetails",
datatype: "json",
mtype: "POST",
ajaxGridOptions: { contentType: 'application/json' },
postData:JSON.stringify(reqData),
colNames: ['ComplaintId',"ComplaintText", ""+complaintDeptName+"", "Status",'ComplaintAdded','ComplaintUpdated','userId'],
colModel: [
{ name: "complaintId",hidden:true},
{ name: "complaintText", width:700},
{ name: "deptName", width:100},
{ name: "comstatus", width:100 },
{ name: "comAdded", width:200 },
{ name: "comUpdated", width:200 },
{ name: "userId",hidden:true },
],
pager: "#pager",
rownumbers:true,
rowNum: 5,
rowList: [5, 10, 20],
viewsortcols:[true,'vertical',true],
viewrecords: true,
gridview: true,
caption: "Complaints grid",
loadonce:true,
autowidth:true,
shrinkToFit:true,
ignoreCase: true,
height:'auto',
jsonReader: {
repeatitems: false,
id: "complaintId",
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
},
loadComplete:function(response){
/*
if (this.p.datatype === 'json') {
console.log('inside');
setTimeout(function() {
console.log('inside');
$("#list")[0].triggerToolbar();
}, 100);
}*/
complaintList.navGrid('#pager',{add:false,edit:false,refresh:true,del:false,
view:true,search:true});
complaintList.jqGrid('filterToolbar',{searchOnEnter:false,stringResult:true,defaultSearch: "cn"});
},
});
}
else{
complaintList.jqGrid('setGridParam',{postData:JSON.stringify(reqData),datatype:'json'}).trigger("reloadGrid");
complaintList.jqGrid('setLabel','deptName',complaintDeptName);
}
Here complaintList is the grid. I am getting data from the server whose type is JSON and converting into local type by using loadonce: true attribute. I want to enable client toolbar filtering
Edit to put initialization of navgrid and toolbar inside loadcomplete as grid is initialized again and again depending on the value of a paramete complaintDeptId
It I correctly understand your problem, then you should replace the parameter
postData:JSON.stringify(reqData)
to the following callback function
serializeGridData: function (postData) {
return JSON.stringify(reqData);
}
It will replace the standard data, which will be sent to the server with your custom string JSON.stringify(reqData). On the other side the standard parameter postData will stay object.
You should remove postData:JSON.stringify(reqData) from parameters of setGridParam too. serializeGridData will use the value of reqData automatically.
I'm trying to use jsGrid in my MVC project as the client would like inline editing and filtering.
However, I cannot get it to load my JSON source into the table.
My js to load the table looks like so:
$("#jsGrid").jsGrid({
height: "50%",
width: "100%",
filtering: true,
inserting: true,
editing: true,
sorting: true,
paging: true,
autoload: true,
pageSize: 10,
pageButtonCount: 5,
deleteConfirm: "Do you really want to delete client?",
controller: {
loadData: function (filter) {
return $.ajax({
type: "GET",
url: "RICInstrumentCode/GetData",
data: filter,
dataType: "json"
});
},
insertItem: function (item) {
return $.ajax({
type: "CREATE",
url: "/api/RICInsrumentCodeTable",
data: item,
dataType: "json"
});
},
updateItem: function (item) {
return $.ajax({
type: "UPDATE",
url: "/api/RICInsrumentCodeTable/" + item.ID,
data: item,
dataType: "json"
});
},
deleteItem: $.noop
//deleteItem: function (item) {
// return $.ajax({
// type: "DELETE",
// url: "/api/data/" + item.ID,
// dataType: "json"
// });
//}
},
fields: [
{ name: "Code", type: "text", title: "RIC Instrument Code", width: 150 },
{ name: "Descr", type: "text", title:"RIC Instrument Code Description", width: 200 },
{ name: "RICInstrumentGroupId", type: "select", title: "RIC Instrument Group", items: countries, valueField: "Id", textField: "Name" },
{ name: "Active", type: "checkbox", title: "Is Active", sorting: true },
{ type: "control" }
]
});
});
The loadData is what I've been working on.
and the JSON the is returned from get data looks like so:
[{"Id":1,"Code":"test1","Descr":"first code test","RICInstrumentGroupId":2,"Active":true},{"Id":2,"Code":"APP","Descr":"Apples and bananas","RICInstrumentGroupId":4,"Active":true},{"Id":3,"Code":"1","Descr":"1","RICInstrumentGroupId":1,"Active":true},{"Id":4,"Code":"3","Descr":"3","RICInstrumentGroupId":3,"Active":false}]
So far I have confirmed that the ajax is firing, changed my array titles to match those of the call, and ensured the return is in valid JSON, what else can I do? Why isn't this working?
I was being stupid,
The bit that sets the table height was set to a 100% in a div that had no height, this was causing the table body to render with a height of 0px, changing the height property to auto fixed it because the data was there all along.
Thanks for the advice though!
I don't know if it is required, but when I look on demo examples (OData Service).
The grid loadData function looks bit different than yours.
loadData: function() {
var d = $.Deferred();
$.ajax({
url: "http://services.odata.org/V3/(S(3mnweai3qldmghnzfshavfok))/OData/OData.svc/Products",
dataType: "json"
}).done(function(response) {
d.resolve(response.value);
});
return d.promise();
}
is accept promise rather than ajax function. so that my be the problem
Demo here: http://js-grid.com/demos/
i have Kendo datagrid which on onLoad method initialize datagrid and fetch some remote data in JSON from API.
I have for example 20 items to display which are correctly displayed. Problem is that i cannot make request for next values (button next is not active).
How i should to that correctly if i want to pass data to API via POST?
I think, that is it something with serverPaging params.
Thanks for any advice or example, hot to solve this issue.
Here is exe example of grid init:
$("#grid").kendoGrid({
selectable: "multiple cell",
navigatable: true,
dataSource: dataPacket,
filterable: true,
//page: 2, // unless the serverPaging option is set to true.
pageSize: 5,
serverFiltering: true,
serverSorting: true,
serverPaging: true,
groupable: true,
pageable: {
pageSizes: [5, 10, 50]
},
sortable: true,
scrollable: false,
reorderable: true,
resizable: true,
columnMenu: true,
height: 550,
toolbar: ["create", "save", "cancel"],
columns: ["id",
Read function:
$scope.initGrid = function () {
var requestParams = {
"token":"test",
"data":{
"test":"test"
}
};
var token = localStorage.getItem($rootScope.lsTokenNameSpace);
var dataPacket;
dataPacket = new kendo.data.DataSource({
transport: {
// READ FUNCTION
read: function (options) {
console.log("List");
// call the service
ApiService.doHttpRequest("POST", $rootScope.apiBaseUrl + "user/list", requestParams)
.success(function (data, status, headers, config) {
// successful data retrieval
console.log("request success");
console.log("state: "+status);
console.log(data);
options.success(data);
// do something with data
})
.error(function (data, status, headers, config) {
// do some stuff
console.log("request processing error");
console.log(data);
});
},
I will post Kendo UI API reference for Kendo UI dataSource here. Take a look at it.
http://docs.telerik.com/kendo-ui/api/framework/datasource#configuration-serverPaging
You need pass needed parameters to fetch more data after first set.
myDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/api/search",
type: "POST",
dataType: "json",
contentType: "application/json",
parameterMap: function( data, type ) {
return JSON.stringify( { query: $("#searchBox").val(), start: data.page, sort: data.sort, pageSize: data.pageSize } );
}
}
},
serverPaging: true,
serverSorting: true,
pageSize: 100,
schema: {
data: "data",
total: "total"
}
});