Grid content JSON conversion - servlets

I have a grid where user and add new rows as many as they want. After adding all the rows, they click the "Save" button. On Save button click, I want to send all the data entered by the user in JSON format to the server side code (i.e. a servlet in my case)
Below is the model and store definition:
Ext.define('Plant', {
extend: 'Ext.data.Model',
fields: [
// the 'name' below matches the tag name to read, except 'availDate'
// which is mapped to the tag 'availability'
{name: 'common', type: 'string'},
{name: 'botanical', type: 'string'},
{name: 'light'},
{name: 'price', type: 'float'},
// dates can be automatically converted by specifying dateFormat
{name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y'},
{name: 'indoor', type: 'bool'}
]
});
// create the Data Store
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Plant'
});
On click of the save button, I am able to get the store like this:
{
text: 'Save',
handler : function(){
//Getting the store
var records = grid.getStore();
console.log(records.getCount());
Ext.Ajax.request({
url: '/CellEditing/CellEditingGridServlet',
method: 'POST',
jsonData: {
//How to assign the store here such that
//it is send in a JSON format to the server?
},
callback: function (options, success, response) {
}
});
}
But I don't know like how to convert the store content into JSON and send it in the jsonData of the ajax request.
I want the JSON data something like this in the server side:
{"plantDetails":
[
{
"common": Plant1,
"light": 'shady',
"price": 25.00,
"availDate": '05/05/2013',
"indoor": 'Yes'
},
{
"common": Plant2,
"light": 'most shady',
"price": 15.00,
"availDate": '12/09/2012',
"indoor": 'No'
},
]
}
Please let me know how to achieve this.
Regards,

Agreed with Neil, the right way to do this is through an editable store outfited with a proxy and a writer. See example here: http://docs.sencha.com/ext-js/4-1/#!/example/grid/cell-editing.html

Store
writer :
{
type : 'json',
allowSingle : true
}
Experiment with allowSingle as per your use case
In your controller
//if you want to set extra params
yourStore.getProxy().setExtraParam("anyParam",anyValue);
// sync the store
yourStore.sync({success : function() {
yourGrid.setLoading(false);
.. },
scope : this // within the scope of the controller
});
You should be creating the model with a new id ( you can ignore it at the server side and use your own key generation , but it lets extjs4 for its internal purposes know that a new record has been created).
creating a model instance
var r = Ext.create('yourModel', { id: idGen++, propA : valA , ... });
insert to grid
store.insert(0,r);
var editPlugin = grid.getPlugin(editPluginId);
editPlugin.startEdit(0,1);
Once you receive a response back the id's can be update to their true value.
in the Store
reader :
{
type : 'json',
root : 'yourdata',
successProperty : 'success',
idProperty : 'id'
}
If you were to use the same grid for handling and editing then you could use the write event or the appropriate event
for more advanced handling in the Store
listeners :
{
write : function(store,operation, eOpts)
{
var insertedData = Ext.decode(operation.response.responseText);
.. do something
}
}
I would recommend using the mvc architecture of Extjs4

This is what I tried and it seems to work:
var store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
model: 'Plant',
proxy: {
type: 'ajax',
url: '/CellEditing/CellEditingGridServlet',
writer: {
type: 'json',
root: 'plantDetails'
}
}
handler : function(){
grid.getStore().sync();
But I am getting an additional parameter in the JSON at the server side:
"id": null
I don't have this id set in my model then where is this coming from? Is there some way to set some values to it rather than having a default null value?

Related

Displaying name and selecting id on select for Twitter Typeahead

I am trying to implement twitter typeahead into my project, having remote as the source. I am able to make the connection between the front end query text and the sql. The return response looks like this:
[
{
id: 1,
name: 'user one'
},
{
id: 2,
name: 'user two'
}
..
]
The typeahead displays the matching items but it includes the id along with the names in the selection, instead of just the name. Second, I want to get the id value on select but the :select always gives the name value instead of the id.
here is my code:
var source = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url:"{{ path('user_typeahead') }}"+'?string=%QUERY', // twig path
wildcard: '%QUERY',
filter: function (results) {
// Map the remote source JSON array to a JavaScript object array
return $.map(results, function (result) {
return {
value: result
};
});
}
}
});
// Initialize the Bloodhound suggestion engine
source.initialize();
$('#typeahead').typeahead(null, {
display: 'value',
source: source.ttAdapter(),
limit:5,
highlight: true,
hint: true
});
$('#typeahead').bind('typeahead:select', function(ev, suggestion) {
console.log(suggestion);
});
Try this,
Display should be set to the property of the json object. display: 'id'
Chain the custom event. Access your id from suggestion.id.
$('#typeahead').typeahead(null, {
display: 'id',
source: source.ttAdapter(),
limit:5,
highlight: true,
hint: true
}).bind('typeahead:select', function(ev, suggestion) {
console.log(suggestion);
});

dgrid JsonRest store not working

I have the following:
require([
"dojo/dom",
"dojo/on",
"dojo/store/Observable",
"dojo/store/JsonRest",
"dojo/store/Memory",
"dgrid/OnDemandGrid"
], function (dom, on, Observable, JsonRest, Memory, OnDemandGrid) {
var store = new JsonRest({
target: 'client/list',
idProperty: 'id'
});
var grid = new OnDemandGrid({
columns: {
"id": "ID",
"number": "Name",
"description": "Description"
},
sort: "lastName",
store: store
}, "grid");
});
client/list is a rest url returning a json object {data:[...]}, but the content of the list never shows up :/
I think the problem is caused by the async data loading, because with a json hard coded object the content show up
EDIT :
I've succeeded in achieving this by using a dojo/request, but the JsonRest shouldn't normally act the same way ? Can someone point me to the right direction ?
require([
'dojo/dom',
'dojo/on',
'dojo/store/Memory',
'dojo/request',
'dgrid/OnDemandGrid'
], function (dom, on, Memory, request, OnDemandGrid) {
request('client/list', {
handleAs: 'json'
}).then(function (response) {
// Once the response is received, build an in-memory store with the data
var store = new Memory({ data: response });
// Create an instance of OnDemandGrid referencing the store
var grid = new OnDemandGrid({
store: store,
sort: 'id', // Initialize sort on id, ascending
columns: {
'id': 'ID',
'number': 'Name',
'description': 'Description'
}
}, 'grid');
console.log(store);
on(dom.byId('queryForm'), 'input', function (event) {
event.preventDefault();
grid.set('query', {
// Pass a RegExp to Memory's SimpleQueryEngine
// Note: this code does not go out of its way to escape
// characters that have special meaning in RegExps
description: new RegExp(this.elements.last.value, 'i')
});
});
on(dom.byId('queryForm'), 'reset', function () {
// Reset the query when the form is reset
grid.set('query', {});
});
});
});
Ok problem found :/
My "client/list" url was returning a json object like this:
{data: [{id:"1", label: "test"}, {id:"2", label: "test"}]}
Turns out that the JsonRest object is already encapsulating data in a data node, so by returning a json like this:
{[{id:"1", label: "test"}, {id:"2", label: "test"}]}
everything worked fine :)

Displaying grid data after switching to Server Side paging

I am converting my application to use Server Side Paging with the Kendo Grid UI. Prior to switching serverPaging to true, I was properly displaying my grid contents, and paging on the client side. However, once I turned on the serverPaging, my data was no longer visible. I have checked the network call, and my data is returning (only 2 records of 8 total) as expected, but I am not seeing it in the grid.
Here is the grid construction:
$v.KendoGrid.makeGrid(gridName, {
columns: [
{ field: 'IdentifierCode', title: 'User Name' },
{ field: 'CompanyName', title: 'Company' },
{ field: 'Email', title: 'Email' }
],
dataSource: {
pageSize: 2,
schema: {
data: 'Data', // records are returned in the data section of the response
model: {
id: 'Id',
fields: {
IdentifierCode: { type: 'string' },
CompanyName: { type: 'string' },
Email: { type: 'string' }
}
},
total: 'Total' // total number of records are in the total section of the response
},
serverPaging: true,
transport: {
read: {
url: window.urlConfigs.root + "Security/UserAccount/PagedListing"
dataType: "json",
type: "GET"
}
}
},
editable: false,
filterable: true,
height: 464,
pageable: true,
scrollable: true,
sortable: true
});
Here is the MVC Controller method:
public ActionResult PagedListing(int pageSize, int skip)
{
var entities = ReadRepo.All();
var total = entities.Count();
var data = entities.Skip(skip).Take(pageSize).Select(MapEntityToViewModel).ToList();
return Json(new { Total = total, Data = data }, JsonRequestBehavior.AllowGet);
}
And here is the data I get back on the network call:
{"Total":8,"Data":[{"Id":"928f0bb2-608b-417b-bf6e-e5c58f85fec2","IdentifierCode":"admin","FirstName":"Administrator","MiddleName":"of","MiddleNameHuman":"of","LastName":"GasStream","DisplayName":"Administrator of GasStream","Email":"admin#example.com","IsExternal":false,"UserTypeHuman":"Internal","CompanyId":"75bb05a4-1ec2-4042-aeba-a229008aca9f","CompanyName":"Entessa Pipeline & Terminal, MLP","CompanyIdentifierCode":"SHA","Password":"wFg/a/NEU6WM8z4YZBUduitIDROfeFz/+Za6leAHnBE=","PasswordChanged":false,"ForceNewPasswordFlag":false,"Settings":[],"RoleGroups":[]},{"Id":"47c29025-cfa8-4447-9ab7-a229008ad088","IdentifierCode":"contractcarl","FirstName":"Carl","MiddleName":null,"MiddleNameHuman":"","LastName":"Smithers","DisplayName":"Carl Smithers","Email":"carl#entessa.com","IsExternal":false,"UserTypeHuman":"Internal","CompanyId":"75bb05a4-1ec2-4042-aeba-a229008aca9f","CompanyName":"Entessa Pipeline & Terminal, MLP","CompanyIdentifierCode":"SHA","Password":"IWdH+qDIOucNrre6V4AgI6Exm2Vq5qkIdXdsWfP6jn4=","PasswordChanged":false,"ForceNewPasswordFlag":false,"Settings":[],"RoleGroups":[]}]}
I suspect I have missed something small, but after looking at this and trying all sorts of possible work-arounds, I cannot see it, so I am asking for some help. I thought once I got the data to return small sets from the Server, things would get simpler.
Thanks in advance,
Drew
I ended up finding the answer. the $v.KendoGrid was a method that wrapped the kendoGrid call itself, and in there something was getting reset to not allow the data to be parsed properly when it came back from the server properly paged.
I have since re-worked the mess so I can establish the necessary parameters in the $v.KendoGrid call for just my type of grid.
Thanks for the help, and the eyes to catch the comma, Brett.
Drew

sencha touch complex models

I'm trying to read entities from a Drupal Services endpoint into my Sencha Touch 2 application. The JSON output looks like this (simplified):
{
nid: 1
title: 'Test'
body: {
'en': [
'This is a test.'
]
}
}
Thats the model's coffeescript code:
Ext.define 'Node',
extend: 'Ext.data.Model'
config:
idProperty: 'nid'
fields: [
{ name: 'nid', type: 'integer' }
{ name: 'title', type: 'string' }
{ name: 'language', type: 'string' }
{ name: 'body', type: 'auto', convert: convertField }
]
proxy:
type: 'jsonp'
url: 'http://www.mydomain.com/rest/node'
convertField = (value, record) ->
console.log value # always "undefined"
return 'test'
Loading the model with a jsonp proxy works, but only the atomic fields (like "nid" and "title") are populated. I tried to add a "convert" function to the models body field, but the value parameter is always undefined.
Is there a way to load complex json data into a models field? Or do I have to use the Model-relations system (which would be a lot of mess ...). I also thought about overriding a Ext.data.Reader, but i don't really know where to start.

ExtJS4 - Reconfiguring a grid in ASP.NET - JSON structure issue

One of ASP.NET's security features is proving to be a mountain to scale here - the "d" property addition when returning a JSON response appears to be confusing ExtJS when I attempt to reconfigure a gridpanel dynamically, causing it to fail when attempting to generate new column structure.
I followed this solution by nicholasnet:
http://www.sencha.com/forum/showthread.php?179861-Dynamic-grid-columns-store-fields
and it works beautifully, until the JSON payload is wrapped around the "d" property, e.g.
{"d":{
"metaData": {
"root": "data",
"fields": [{
"type": "int",
"name": "id",
"hidden": true,
"header": "id",
"groupable": false,
"dataIndex": "id"
}, ...omitted for brevity...]
},
"success": true,
"data": [{
"id": "1",
"controller": "Permissions",
"description": "Allow to see permission by roles",
"administrator": true,
"marketing": false
}]
}
}
I can't work out how to tell ExtJS to skirt around this problem. I've tried setting the "root" property of the AJAX reader to "d.data" but that results in the grid showing the correct number of rows but no data at all.
I've all the property descriptors required for column metadata ("name", "header", "dataIndex") in the JSON so I don't believe the JSON structure to be the cause. My main lead at the moment is that on the event handler:
store.on
({
'load' :
{
fn: function(store, records, success, operation, eOpts)
{
grid.reconfigure(store,store.proxy.reader.fields);
},
scope: this
}
}, this);
The fields in historyStore.proxy.reader.fields part is undefined when I pass the "d"-wrapped JSON. Anyone have any ideas on why this is or how to solve this issue?
edit: my Store/proxy
Ext.define('pr.store.Store-History', {
extend: 'Ext.data.Store',
model: 'pr.model.Model-History',
proxy: {
type: 'ajax',
url: '/data/history.json',
reader: {
type: 'json',
root: 'd'
}
}
});
Ext.define('pr.store.Store-History', {
extend: 'Ext.data.Store',
model: 'pr.model.Model-History',
proxy: {
type: 'ajax',
url: '/data/history.json',
reader: {
type: 'json',
root: 'data',
readRecords: function(data) {
//this has to be before the call to super because we use the meta data in the superclass readRecords
var rootNode = this.getRoot(data);
if (rootNode.metaData) {
this.onMetaChange(rootNode.metaData); // data used to update fields
}
/**
* #deprecated will be removed in Ext JS 5.0. This is just a copy of this.rawData - use that instead
* #property {Object} jsonData
*/
this.jsonData = rootNode;
return this.callParent([rootNode]); // data used to get root element and then get data from it
},
}
}
});
Update:
you are not getting fields in reader because the default code for getting fields from data doesn't handle your wrapped data, so you need to change 'readRecords' function to handle your custom data

Resources