I have a jqGrid working OK using the local datatype, but I now want the values to be loaded via json but having trouble changing it.
This is my jqGrid code
jQuery("#grid").jqGrid({
datatype: "json",
url: "/controller/getItems?id=2",
width: 1405,
colNames: ['id', 'surname'],
colModel: [
{ name: 'id', index: 'id', editable: false, hidden: false, hidedlg: true },
{ name: 'surname', index: 'surname', editable: true }
],
onSelectRow: function (id, status, e) {
...
},
editurl: url,
...
So the method to get the JSON is sucessfully fired.
[HttpGet]
public ActionResult getItems(string id)
{
List<model> items = method.getItems(id);
string jsonText = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(items);
return Json(jsonText, JsonRequestBehavior.AllowGet);
}
The column names in the JSON do match the colModel names
Example of the json being returned - what the object jsonText above contains
[{"id":434,"surname":"Woods"},
{"id":435,"surname":"Adams"}]
Is there anything I have done wrong or am missing?
Thanks
I suppose that the error in in using of System.Web.Script.Serialization.JavaScriptSerializer().Serialize. You need just return Json(items, JsonRequestBehavior.AllowGet);. Additionally you can remove the column id from the colModel. The id value will be still read and assigned as the value of id attribute of the rows (id of <tr> elements of the grid) known as rowid. You should add loadonce: true option to the grid because you don't implemented paging of data on the server side and to add gridview: true (if you not already use it) to have better performance and autoencode: true to interpret input data as texts instead of HTML fragments.
UPDATED: In case of usage old version of jqGrid one have to include jsonReader parameter which corresponds the format of input data:
jsonReader: {
repeatitems: false,
root: function (obj) { return obj; }
}
One should still use loadonce: true option additionally.
Related
I'm very new to ExtJS and wanted to achieve the following:
I have a model with data something like this:
{
"Account_Enabled": true,
"Requirements_gathered": true,
"work_done": false,
"deadlines": {
"Account_Enabled": true,
"Requirements_gathered": false
}
}
There are no multiple rows. Only a single row returned from the database.
I want to display the data in a grid with three columns
Column1: The name of the column
Column2: A checkbox that shows whether the value is true or false
Column3: A checkbox that shows whether the column name present in "deadlines" or not
Ex:
Account_Enabled True True
Requirements_Gathered True False
work_done False Undefined(Checkbox need to be disabled)
Basically, i need to convert that single row into three columns.
Also, i need to the update the store when the user checks/uncheks the checkboxes
May i know if there is any way to achieve this via ExtJS grids? or is there any better idea?
Thanks in advance
There is no direct way to bind your json response in the format you mention to the grid store.
What you need to do is to manipulate the response the match grid columns required.
Check this working example ExtJs Fiddle
//Your Original Response
let response = '{"Account_Enabled": true, "Requirements_gathered": true, "work_done": false, "deadlines": {"Account_Enabled": true, "Requirements_gathered": false}}';
// Convert your response to object
let jsonDecode = Ext.decode(response);
//This function to convert your response to match grid store
let dataConvert = function(jsonObj){
//Returned array object
let data = [];
// To get Object of deadlines and know if the property exist or not
let availableData = jsonObj.deadlines
//Loop throw object property
for(var objProperty in jsonObj){
//Ignore deadlines property
if(objProperty=="deadlines"){
continue;
}
//Adding the object to the array "objPropery" will return the property name
//"jsonObj[objProperty]" will return the value of property if it is true or flase
//"availableData[objProperty]" will return the value if exist in availableData
data.push({colName:objProperty,isReqGathered:jsonObj[objProperty],isWorkDone:availableData[objProperty]})
}
return data
}
let gridStore = Ext.create('Ext.data.Store', {
storeId: 'gridStoreId',
fields: ['colName', 'isReqGathered', 'isWorkDone'],
data: dataConvert(jsonDecode)
});
Ext.create('Ext.grid.Panel', {
title: 'Test Store Filter',
width: 500,
height: 400,
renderTo: Ext.getBody(),
store: gridStore,
columns: [{
dataIndex: 'colName',
text: 'colName'
}, {
dataIndex: 'isReqGathered',
text: 'isReqGathered'
}, {
dataIndex: 'isWorkDone',
text: 'isWorkDone'
}]
})
I'm working with this bootstrap library and actually everything works fine. The question is, Can bootstrap-table generate header automatically in depend of JSON file? I've tried to find any information about that, but unlucky. Now my header is generated from script like from this example:
function initTable() {
$table.bootstrapTable({
height: getHeight(),
columns: [{
field: 'field1',
title: 'title1',
sortable: true
}, {
field: 'field2',
title: 'title2',
sortable: true
}, {
field: 'field3',
title: 'title3',
sortable: true
}, {
field: 'Actions',
title: 'Item Operate',
align: 'center',
events: operateEvents,
formatter: operateFormatter
}
],
formatNoMatches: function () {
return "This table is empty...";
}
});
Does anyone how to generate header automatically?
Populating from a flat json file is definetly possible but harder than from a seperate (slimmer and preped) data request, because title and other attributes 'might' have to be guessed at.
Ill show basic approach, then tell you how to make it work if stuck with a flat file that you CAN or CANT affect the format of (important point, see notes at end).
Make a seperate ajax requests that populates var colArray = [], or passes direct inside done callback.
For example, in callback (.done(),.success(), ect) also calls to the function that contains the js init code for the table.
You might make it look something like this:
function initTable(cols) {
cols.push({
field: 'Actions',
title: 'Item Operate',
align: 'center',
events: operateEvents,
formatter: operateFormatter
});
$("#table").bootstrapTable({
height: getHeight(),
columns: cols,
formatNoMatches: function () {
return "This table is empty...";
}
});
}
$(document).ready(function(){
$.ajax({
method: "POST",
url: "data/getColumns",
// data: { context: "getColumns" }
datatype: "json"
})
.done(function( data ) {
console.log( "getCols data: ", data );
// Prep column data, depending on what detail you sent back
$.each(data,function(ind,val){
data.sortable = true;
});
initTable(data);
});
});
Now, if you are in fact stuck with a flat file, point the ajax towards that then realise the question is whether you can edit the contents.
If yes, then add a columns array into it with whatever base data (title, fieldname, ect) that you need to help build your columns array. Then use responseHandler if needed to strip that columns array if it causes issues when loading into table.
http://bootstrap-table.wenzhixin.net.cn/documentation/#table-options
http://issues.wenzhixin.net.cn/bootstrap-table/ (click 'see source').
If no, you cant edit contents, and only have the fieldname, then look at using that in the .done() handler with whatever string operation (str_replace(), ect) that you need to make it look the way you want.
I'm trying to POST a form using extjs. I have tagfields that need to be sent as json arrays. Here is one tagfield:
{
xtype: 'tagfield',
fieldLabel: 'Product(s)',
name: 'productIds',
store: {
type: 'products'
},
valueField: 'productId',
displayField: 'productName',
encodeSubmitValue: true //this is supposed to send an array per https://docs.sencha.com/extjs/6.0/6.0.0-classic/#!/api/Ext.form.field.Tag-cfg-encodeSubmitValue
}
Here is the Ajax submit:
Ext.Ajax.request({
url: 'api/events/create',
method:'POST',
headers: { 'Content-Type': 'application/json' },
params : Ext.JSON.encode(form.getValues()),
success: function(form, action) {
Ext.Msg.alert('Success', action.result);
},
failure: function(form, action) {
//console.log(form.getForm().getValues());
Ext.Msg.alert('Submission failed.', 'Please make sure you selected an item for each required field.', action.result);
}
});
The JSON payload ends up looking like this:
{ "productIds": "[1,2]" }
The above array cannot be deserialized out of the string (the backend uses Jackson to de-serialize).
Does anyone know how to send the above as { "productIds": [1,2] } ?
So when I removed encodeSubmitValue, it sent tagfield as an array without quotes automatically. Thanks for the ideas anyway!
Here's the tagfield without encodeSubmitValue:
{
xtype: 'tagfield',
fieldLabel: 'Product(s)',
name: 'productIds',
store: {
type: 'products'
},
valueField: 'productId',
displayField: 'productName'
}
As you can see by executing Ext.JSON.encode({products: [1,2]}); the double quotes are not being added by the encode function. The problem is the Ext concept of making every form field compatible with old HTML forms and therefore return a string. If you override the getValue() (or possibly getRawValue()) function you can make it return the actual array.
I am using jqGrid to show data in tabular format, using JSP and Servlet.
I have two dependent drop-downs to show.
Show State
Show City
Following is relevant code:
colNames:['User ID', 'Name','State','City'],
colModel:[
{name:'USERID',index:'USERID',....},
{name:'NAME',index:'NAME',....},
{
name:'STATE',
index:'STATE',
width:125,
sortable:true,
edittype:"select",
editoptions: {
maxlength: 15,
dataUrl: 'MYServlet?action=getState',
dataEvents :[{
type: 'change',
fn: function(e) {
var thisval = $(e.target).val();
$.post('MyServlet?action=getCity='+thisval,
function(data){
var res = $(data).html();
$("#STATE").html(res);
});
}
}]
}
},
{
name:'CITY',
index:'CITY',
width:125,
sortable:true,
editable:true,
edittype:"select",
editoptions:{maxlength: 50 , value: 'Select:Select'}
}
],
Above code is working fine for dependent drop-downs. Now I want to pass USERID with datUrl in editoptions of STATE column. like
dataUrl: 'MYServlet?action=getState&userid='+userid
But I am not able to get USERID in dataUrl.
So any suggestions will be appreciated.
I suggested some extensions of dataUrl which are now part of jqGrid. It's usage of postData property of editoption defined as function (see the answer) or usage of dataUrl as function directly (see here and here). The first feature is included in jqGrid 4.4.2, but the second is included after 4.5.2 was released. So I recommend you to use postData as function.
What you need to do is adding postData property to editoptions of STATE column in the form
editoptions: {
dataUrl: "MYServlet",
postData: function (rowid) {
return {
action: "getState",
userid: $(this).jqGrid("getCell", rowid, "USERID")
};
}
}
If the values of USERID column is unique and you use key: true then rowid are already the same value as the value of USERID column. In the case you can simplify the above code and use rowid directly instead of $(this).jqGrid("getCell", rowid, "USERID").
I'm trying to learn how to use the EXTJS grids for some simple CRUD operations over a table in a admin app.
I have a simple grid that allows someone to edit users, the store is defined as:
var userDataStore = new Ext.data.Store({
id: 'userDataStore',
autoSave: false,
batch: true,
proxy: new Ext.data.HttpProxy({
api: {
read: '/Admin/Users/All',
create: '/Admin/Users/Save',
update: '/Admin/Users/Save'
}
}),
reader: new Ext.data.JsonReader(
{
root: 'Data',
idProperty: 'ID',
totalProperty: 'total',
successProperty: 'success',
messageProperty: 'message'
}, [
{ name: 'ID', type: 'string', allowBlanks: false },
{ name: 'NT_ID', type: 'string', allowBlank: false },
{ name: 'EMail', type: 'string', allowBlank: false },
{ name: 'Name', type: 'string', allowBlank: false },
{ name: 'Enabled', type: 'bool', allowBlank: false },
{ name: 'CurrentRoleCode', type: 'string', allowBlank: false}]
),
writer: new Ext.data.JsonWriter(
{
encode: false,
writeAllFields: true,
listful: true
})
});
This is bound to a grid, and I am able to load and save users without issue. The save button looks like this:
var saveButton = new Ext.Button({
text: 'Save',
disabled: true,
handler: function() {
userDataStore.save();
pageState.ClearDirty();
saveButton.disable();
}
});
However, when creating a new user, the JSON POST for the user is posted to the same REST service end point as "Update", with the only difference being that no ID value is posted (as one is only set in the store when loading from the server).
This works, and I am able to create users.
The save REST service emits back the created row with the new database ID, and I was under the assumption that EXTJS would automatically bind the new generated database ID to the row. This allows the user to further edit that row, and cause an update instead of a insert.
Instead, the row continues to have a blank user ID, so an additional save creates another new user.
So either:
EXTJS is supposed to resolve generated row ID's automatically and I am just doing something wrong.
I am supposed to manually reload the grid after each save with an additional REST call.
I've been looking at EXTJS documentation and forums, but I am unclear on the proper approach.
Can someone clarify?
EDIT: I tried returning Success = True in JSON to match the SuccessProperty, however this still didn't seem to work.
EDIT #2: So far the only thing I've found that works is doing "userDataStore.reload()" after saving, however because I was returning the contents of the store back after saving, I was hoping that EXTJS would understand that and update the row values.
I've got an idea that may help you. Let't suppose that user added a new
record in grid, in that moment add a new property newRecOrderNo to the record to
identify the record after response. When user will post data to server after
inserting you must get a new ID and associate it to newRecOrderNo
(like Map<Integer,Integer>). Then return json object like that :
{
success : true,
newIdes : {
1 : 23,
2 : 34
}
}
Then when you get response do set proper IDs to records:
userDataStore.each(function(rec){
if(rec.data.newRecOrderNo){
rec.data.ID = response.newIdes[rec.data.newRecOrderNo];
delete rec.data.newRedOrderNo;
}
})
})
Yes, it sets id (and also other fields, if server returns modified values of them), if create ajax backend returns record with set id, at least in extjs 4.1. You should return inserted record, with id set, under 'root' key as json dictionary, in this example root is 'Data', i.e.:
{
"Data": {
"ID": 8932,
"NT_ID": 28738273,
...
"CurrentRoleCode": "aaa",
},
"success": true
}
You need reload store with new params in savebtn handler
like
store.reload();
of course you can add more params to load action