Having trouble refreshing Gridx using JsonRest - javascript

When an account is chosen, I would like to show all related contacts in contactGrid.
I can do this with XhrGet, but I would like to be using JsonRest.
Here is how I setup the Grid:
function contactTabSetup() {
var structure = [{ field: 'id', name: 'Id', width: '5em' },
{ field: 'firstName', name: 'First Name', width: '12%' },
{ field: 'lastName', name: 'Last Name', width: '12%' },
{ field: 'email', name: 'Email', width: '12%' },
{ field: 'description', name: 'Description' },
{ field: 'mobileNumber', name: 'Mobile Phone', width: '12%' }];
var contactGrid = new Grid({
id: 'contactGrid',
pageSize: 20,
cacheClass: Cache,
structure: structure,
noDataMessage: "No contacts found",
modules: [SingleSort]}, contactTab);
contactGrid.startup();
}
Here is how I want to populate the grid:
function contactLoad(acctIds) {
var grid = registry.byId("contactGrid");
grid.model.clearCache();
grid.setStore(JsonRest({target:"//localhost:8080/program/contacts/byAccount/" + acctIds}));
grid.body.refresh();
}
The correct Json response is being returned (as viewed on console):
{
"description": "Mike is a cool guy",
"email": "mike#mike.net",
"firstName": "Mike",
"id": 1503,
"lastName": "Smith",
"mobileNumber": "555-555-5555"
}
... but I can't get the grid to show the new data.
Any help would be appreciated!
Thank you
I tried many additional ways, without success...
This is where I am stuck - not sure what else to try.
I make the JsonRest call, get back the Json Object, and print it out to console.
Seeing that the json response looks good I try to setStore and this error is thrown: "s.query is not a function in dojo.js" (line 382). Is this a bug, or am I missing something? Thank you.
// s.query is not a function in dojo 10.0.1
grid.model.clearCache();
var store = new JsonRest({target:"//localhost:8080/program/contacts/byAccount"});
store.get(acctIds).then(function(items){
console.log(items);
grid.setStore(items);
});
grid.body.refresh();
I found it. Change:
grid.setStore(items);
to
grid.setStore(new ItemFileReadStore({data: {items : result}}));
Does anyone know how to just use JsonRest and not also include ItemFileReadStore?
Thank you,
Chris

My little piece of advice is to try to set store up once and use filter instead.
grid.filter({"acctId":"..."});
The second thing is that store sometimes requires idAttribute definition i.e.
JsonRestStore({target:"...", idAttribute:"id"});

Related

How to create a dynamic (on the fly) form in Sencha Touch

I am working in a sencha touch ap and I need to generate views with dynamic forms.
Configuration comes from the backend (JSON) and depending of this I paint a component or other.. for example:
"auxiliaryGroups": [
{
"id": "1000",
"name": "Basic Data",
"fields": [
{
"id": "1001",
"name": "Company name",
"editable": true,
"mandatory": true,
"calculation": true,
"internalType": "T",
"type": "textfield",
"options": []
}
]
}
],
Where type is related xtype in Sencha.
In the view I am creating all options of fields:
{
xtype : 'fieldset',
itemId: 'auxiliaryFieldsGroup3',
title: 'Requirements',
//cls : 'headerField',
items:[
{
xtype: 'togglefield',
name: 'f6',
label: 'Auxiliary field R1'
},
{
xtype: 'selectfield',
name: 'f10',
label: 'Auxiliary field R5',
placeHolder: 'Select one..',
options: [
{text: 'First Option', value: 'first'},
{text: 'Second Option', value: 'second'},
{text: 'Third Option', value: 'third'}
]
},
{
xtype: 'textfield'
}
]
}
And I receive the configuration from the server, I understand the view like a store of different fields, and from the controller, it should add only fields specified in the json object.
How to create this dynamically following MVC concept?
Thank you
I assume that you have all the fields in the auxiliaryGroups.fields array.
After loading the form data from AJAX you can do it like this in your success call.
succses:function(response){
var response = Ext.decode(response.responseText);
var fields = response.auxiliaryGroups.fields;
var form = Ext.create("Ext.form.Panel",{
// here your form configuration.
cls:"xyz"
});
Ext.Array.forEach(fields,function(field){
var formField = {
xtype: field.type,
label: field.name,
name: field.id
};
form.add(formField);
});
Ext.Viewport.add(form);
form.show();
}
Based on my comment on your question, my idea about dynamic form generation is using ExtJS syntax to load form definition would be something like the code below; of course it would be extended and the data can be loaded from the server.
Ext.require([
'Ext.form.*'
]);
Ext.onReady(function() {
var data = [{
fieldLabel: 'First Name',
name: 'first',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'last'
}, {
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype: 'email'
}, {
xtype: 'timefield',
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
}];
var form = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Simple Form',
bodyStyle: 'padding:5px 5px 0',
width: 350,
fieldDefaults: {
msgTarget: 'side',
labelWidth: 75
},
defaultType: 'textfield',
defaults: {
anchor: '100%'
}
});
form.add(data);
form.render(document.body);
});
update:
When you create a view in run-time, communication between view and controller might be problematic because the controller doesn't know anything about the view. considering that the controller is responsible for initializing the view with appropriate data and handling view's events, data binding mechanism in ExtJS can solve the first part (initializing the view) which is described at View Models and Data Binding, the second part (handling view's events) can be solved with general methods in the controller, every element in the view should send its event to some specific methods and the methods based on the parameters should decide what to do.
This approach makes your methods in the controller a little fat and complicated that is the price of having dynamic form.
It is worth to mention that EXTJS raises different events in the life cycle of controllers and views and you should take benefit of them to manage your dynamic form.
I don't know about Touch, but in ExtJS, I usually do it by using the add function of a fieldset. You just loop through all your records, and create the fields on the fly.
var field = Ext.create('Ext.form.field.Text'); //or Ext.form.field.Date or a number field, whatever your back end returns.
Then set correct config options on field then
formFieldset.add(field);

Kendo UI Grid - Binding to navigation properties

I am using the Kendo UI grid and am display a role of models. Each model has a navigation property, and I am trying to display a field that exists in this navigation property.
//schema for my kendo data source
schema: {
data: function (data) {
return data || [];
}
}
......................................................
$("#FAAFreqGrid").kendoGrid({
dataSource: FAADS,
columns: [
{ field: "Id", title: "Freq ID", format: "{0:c}", width: "120px" },
{ field: "Frequency", title: "Frequency Test" format: "{0:c}", width: "120px" },
{ field: "FREQ_POOL", title: "FAATEST", format: "{0:c}", width: "120px" },
{ command: ["edit", "destroy"], title: " ", width: "250px" }
],
toolbar: ["create"],
editable: "inline",
pageable: true
});
If I go to my Web API Url, I get a json response of:
[{"$id":"1","Frequency":"164.1375","FREQ_POOL":{"$id":"2","IsAM":true,......etc}
FREQ_POOL is my navigation property, and it has the data I want. Frequency exists and displays in my grid properly. But my FREQ_POOL field says [object Object], and if I try to say "FREQ_POOL.IsAM", it says IsAM is not defined. I cannot get it to bind to any property I can bind to any other non-navigation field. How do I make this work? The data exists in the JSON object that is returned, but the binding just isn't working correctly. Thanks.
You could set a template for the column in question, like this:
$("#grid").kendoGrid({
columns: [ {
field: "name",
template: "<strong>#: name.first#, #: name.last# </strong>"
}],
dataSource: [ { name: { first: 'Jane', last: 'Doe' } }, { name: { first: "John", last: 'Doe' } } ]
});
the template can then be used to show object in the dataset
more info, you could find here
For the editing, you could then also define the cell editor, with an extra template or function, more info about that, you could find here.

Browser crashes when binding a foreign source datafield in jqx.dataAdapter

I'm trying to build a grid using jQWidgets (jqxGrid) with a column which displays values from a foreign data source, using jqx.dataAdapter, but the browser crashes when I try to call the dataBind() method.
Here's my (browser crashing!) jsfiddle:
http://jsfiddle.net/qYyRs/6/
Partial code:
var Area_DataSource = {
datatype: 'array',
localdata: Area_Data,
async: false,
datafields: [{
name: 'Id'
}, {
name: 'Name'
},{
name: 'PlantId'
},{
name: 'PlantName',
value: 'PlantId',
values: {
value: 'Value', // the problematic field
name: 'Name',
source: Plant_DataAdapter.records
}
}]
};
var Area_DataAdapter = new $.jqx.dataAdapter(Area_DataSource);
Area_DataAdapter.dataBind(); // booom!
Base example from jQWidgets website:
http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxgrid/index.htm#demos/jqxgrid/gridkeyvaluescolumnwitharray.htm
This is a confirmed issue:
http://www.jqwidgets.com/community/topic/browser-crashes-foreign-datafield-in-jqx-dataadapter/
"We debugged the issue and confirm it. It will be resolved in jQWidgets
2.8.
Best Regards, Peter Stoev
jQWidgets Team http://www.jqwidgets.com"

How to remotely sort an Ext grid column that renders a nested object?

Simple question here, and I'm really surprised I cannot find an answer to it anywhere.
I have the following product model:
Ext.define('Product', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'manufacturer', type: 'auto'}, // i.e. nested object literal
],
});
As can be seen, a product has a nested object inside it that contains details about a manufacturer (id, name, description, etc.).
I display products in an Ext.grid.Panel, like so:
Ext.create('Ext.grid.Panel', {
title: 'Products',
...
remoteSort: true,
columns: [
{text: 'Id', dataIndex: 'id', sortable: true},
{text: 'Name', dataIndex: 'name', sortable: true},
{text: 'Manufacturer', dataIndex: 'manufacturer', sortable: true, renderer: function(manufacturer) {
return manufacturer.name; // render manufacturer name
}
},
],
});
As you can see, all three columns are configured to be sortable, and I am using remote sorting. This works for the first two columns, but the third column (manufacturer) is giving me trouble.
For instance, when a user sorts the grid by product name, Ext sends the following JSON to the server:
{ sort: [{ property: 'name', direction: 'ASC' }] }
This is fine, because the server knows to simply sort by each product's name property.
But when a user sorts the grid by manufacturer, the JSON sent is:
{ sort: [{ property: 'manufacturer', direction: 'ASC' }] }
Since the manufacturer is an object, this does not give the server any idea which property of the manufacturer it should sort by! Is it the manufacturer's id? Or is it the manufacturer's name? Or something else?
For my grid, since I render the manufacturer's name, I'd like to sort it by name. But I see no way to tell the server this. And I certainly don't want to make my server just sort by the manufacturer's name all the time.
If the JSON was sent like this it would be ideal:
{ sort: [{ property: 'manufacturer.name', direction: 'ASC' }] }
Sadly, Ext does not seem to do that (?). So, what's the solution?
Okay, I asked on the Sencha Forums and got a response. It appears you can override getSortParam() in the column config. Example:
columns: [
...
{
header: 'Manufacturer',
dataIndex: 'manufacturer',
sortable: true,
renderer: function(manufacturer) {
return manufacturer.name; // render manufacturer name
},
getSortParam: function() {
return 'manufacturer.name';
},
}
...
]
This will send the ideal JSON I described in my OP. Now I just need to make my server parse this properly! :)

ExtJS grid filters: how can I load 'list' filter options from external json?

I have a ExtJS (4.0) grid and it works fine. Now I want it to advance it a bit by adding filters to it. I want users to be able to filter items by the status.
I have created the following store:
var status_store = Ext.create('Ext.data.Store', {
model: 'Statuses',
proxy: {
type: 'ajax',
url: '/json/statuses/',
reader: 'json'
}
});
and I can see it loads, /json/statuses/ will return the following json object:
[
{
"name": "OK",
"isActive": true
},
{
"name": "Outdated",
"isActive": true
},
{
"name": "New",
"isActive": true
}
]
Now I define the filters:
var filters = {
ftype: 'filters',
encode: encode,
local: local,
filters: [{
type: 'list',
dataIndex: 'name',
store: 'status_store',
labelField: 'name'
}]
};
and add the filter to my column definition:
{text: 'Status', width: 120, dataIndex: 'status', sortable: true, filterable: true, filter: {type: 'list'}},
What happens is I get the following error when the grid loads:
Uncaught TypeError: Object json has no method 'read' (ext-all-debug.js:25702)
and when I click on the column header for the menu:
Uncaught TypeError: Object status_store has no method 'on' (ListMenu.js:69)
How can I fix this or am I doing something conceptually wrong?
Here is the full quote of my code just in case: http://pastebin.com/SNn6gFJz
Thanks for Diagnosing the problem. The 4.1 fix is this modify ListMenu.js
in the else part of the constructor
replace
me.store.on('load', me.onLoad, me);
with
// add a listener to the store object
var storeObject = Ext.StoreMgr.lookup(me.store);
storeObject.on('load', me.onLoad, me);
me.store = storeObject;
filters: [{
type: 'list',
dataIndex: 'name',
store: 'status_store',
labelField: 'name' ,
options:[a,b]
}]
You also have to give the options in list filters.
I was having a similar problem. I followed the #jd comment on the other answer here but the options menu just said "loading...". I resolved it with a bit of a hack here.

Categories

Resources