ExtJS - DWR proxy with json store? - javascript

I'm trying to make a JsonStore use a function that takes arguments and executes asynchronously, but I'm not sure how to do this.
myMethod takes a callback, but how do I tie the callback data to the JsonStore?
store = new Ext.data.JsonStore({
proxy: new Ext.data.DirectProxy(
{
directFn:(new function(){return MyDwrService.myMethod('test')}),
}),
autoLoad:true,...
I tried using a DwrProxy implementation, but now when I don't pass fields to JsonReader, no data populates my grid, and when I do pass fields, a bunch of blank rows are created. What gives?
store = new Ext.data.Store({
proxy: new Ext.ux.data.DwrProxy({
apiActionToHandlerMap:{
read: {
dwrFunction: MyService.myMethod,
getDwrArgsFunction: function() {
return ["testUser"]
}
}
}
}),
reader: new Ext.data.JsonReader({fields:myFields}),
autoLoad:true,
fields:myFields,
remoteSort:true
});

Use DWR3 with JSONP enabled and you won't need a proxy.

You definitely need to include fields in the reader but I don't understand why there are blank rows. I'm pretty sure we don't get any empty records - maybe the allowBlank:false sorts it out.. if it's any use, this is our code:
var myReader = new Ext.data.JsonReader({
root : 'objectsToConvertToRecords',
idProperty: 'id',
fields : [
{name: 'id', allowBlank:false},
{name: 'foo', allowBlank:false},
{name: 'bar', allowBlank:false}
]
});
var dwrProxy = new Ext.ux.data.DwrProxy({
apiActionToHandlerMap : {
read : {
dwrFunction : RemoteClass.remoteReadMethod,
getDwrArgsFunction: function(request, newData, oldData) {
return [request.params.myId];
}
}
create : {
dwrFunction : RemoteClass.remoteCreateMethod,
getDwrArgsFunction: function(request, newData, oldData) {
return [newData];
}
}
update : {
dwrFunction : RemoteClass.remoteUpdateMethod,
getDwrArgsFunction: function(request, newData, oldData) {
return [newData];
}
}
destroy : {
dwrFunction : RemoteClass.remoteDestroyMethod
}
}
});
var store = new Ext.data.Store({
proxy: dwrProxy,
reader: myReader,
writer : myWriter,
autoLoad : true,
autoSave: true,
baseParams: { tiploc: this.tiploc }
})

Related

Dojo Javascript variable scope

I am using dgrid and i am attempting to set the dataStore externally. When the page loads i call aliasTicket.load() to create the grid. At the time the grid is loading the datasource is null. When a query is executed the setAliasSource(aliasData); is set.
There are no errors however the grid is still empty. The aliasStore is being updated with data however it isn't being reflected on the grid even after the grid is refreshed. How can i get the data reflected in the grid after the query?
Javascript Object
var aliasTicket = (function (){
var aliasData = [];
require([ "dojo/store/Observable", "dojo/store/Memory"]);
var aliasStore = new dojo.store.Observable(new dojo.store.Memory({
data: aliasData,
idProperty: "id"
}));
return{
load:function(){
require([
........
], function(declare, Memory, OnDemandGrid, ColumnSet, Selection,
selector, Keyboard, DijitRegistry, editor, ColumnHider,
registry, Observable,lang) {
aliasData = this.aliasData;
var Store = this.aliasStore = new dojo.store.Observable(new dojo.store.Memory({
data: aliasData,
idProperty: "id"
}));
console.log(Store);
var CustomAliasNameGrid = declare([OnDemandGrid, selector, Selection, Keyboard, editor, DijitRegistry, ColumnHider]);
var aliasNameGrid = new CustomAliasNameGrid({
store: Store,
columns: {
id: {
label: "Id",
field: "id",
hidden: true,
autoSizeColumn: true
},
employeeTicketId: {
label: "Employee Ticket Id",
field: "employeeTicketId",
hidden: true,
autoSizeColumn: true
},
chkBox: selector({}),
aliasName: {
label: "Alias Names",
field: "aliasTicketName",
autoSizeColumn: true,
formatter: function(str) {
return str.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
}
},
selectionMode: "none",
loadingMessage: "Loading data...",
noDataMessage: "No results found....",
allowSelectAll: true
}, "aliasNameGrid");
aliasNameGrid.refresh()
});
},
setAliasSource: function (data){
console.log(data);
this.aliasSource = data;
},
setAliasData: function (data){
this.aliasData = data;
},
getAliasSource: function (){
return this.aliasSource;
}
};
})();
Setting Data Store Data
aliasData = [{.....},
{.....},
{......];
require(["dijit/dijit"]);
aliasTicket.setAliasSource(aliasData);
dijit.byId('aliasNameGrid').refresh();
You are setting 'this.Store' to an object array, not a real 'dojo store' object. Following your code I can not see where you actually use 'this.Store'. Inside the grid code I do see a local variable named 'Store'.
So I'm not sure if I'm following your code example here but, you should 'set' the store of the grid and then refresh it. Something like this.
setAliasSource: function (data){
console.log(data);
this.Store = data;
dijit.byId('aliasNameGrid').set("store",new dojo.store.Observable(new dojo.store.Memory({ data: data,idProperty: "id"}));
dijit.byId('aliasNameGrid').refresh();
},

Google Places Auto-complete in extjs4

I am using extjs4 and Spring at server side. I need to integrate Google Places Auto-complete inside one of the extjs4 form. Is there any way this can be done. I am not sure weather we can integrate Google Auto-complete with extjs I have searched but not find anything more specific to my requirement. Please guide me ..... look at my code ...
Ext.define('abce.view.ReportMissing', {
extend : 'Ext.panel.Panel',
alias : 'widget.report_missing',
bodyPadding : 10,
autoScroll : true,
frame : true,
items : [{
id : 'report_form',
xtype : 'form',
frame : true,
defaultType : 'textfield',
items : [{
xtype : 'combobox',
store : new Ext.data.Store({
autoLoad : true,
//fields : ['memberName', 'email'],
proxy : {
type : 'ajax',
headers : {
'Content-Type' : 'application/json',
'Accept' : 'application/json'
},
url : 'http://maps.googleapis.com/maps/api/geocode/json?address=hyd+&sensor=false',
remoteSort : true,
method : 'GET',
reader : {
type : 'json',
successProperty : 'status'
}
}
})
}]
});
https://developers.google.com/places/documentation/autocomplete
Why not instead of use the sencha combobox, use a simple text input as suggest the google api autocomplete documentation.
(I first try with a just common textfield but it didn't work)
Then declare a panel or component with html as the following example, and then assign the render:
xtype: 'component',
html: '<div> <input id="searchTextField" type="text" size="50"> </div>',
listeners: {
render: function () {
var input = document.getElementById('searchTextField');
autocomplete = new google.maps.places.Autocomplete(input, { types: ['geocode'] });
autocomplete.addListener('place_changed', this.fillInAddress);
},
And result in this:
The proxy cannot be used to retrieve data from a URL on a different origin. See the limitations section of Ext.data.proxy.ajax for more information.
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.proxy.Ajax
You will probably need to set up an endpoint on your server to proxy the request to Google if you want to use that API.
I was looking for a way to do the same, and I came up writing a custom proxy against the google map javascript library
Then I used this custom proxy in a regular combo box
ComboBox:
Ext.create('Ext.form.field.ComboBox', {
store: {
fields: [
{name: 'id'},
{name: 'description'}
],
proxy: 'google-places'
},
queryMode: 'remote',
displayField: 'description',
valueField: 'id',
hideTrigger: true,
forceSelection: true
});
Custom proxy: (inspired from Ext.data.proxy.Ajax)
Ext.define('com.custom.PlacesProxy', {
extend: 'Ext.data.proxy.Server',
alias: 'proxy.google-places',
constructor: function() {
this.callSuper();
this.autocompletePlaceService = new google.maps.places.AutocompleteService();
},
buildUrl: function() {
return 'dummyUrl';
},
doRequest: function(operation) {
var me = this,
request = me.buildRequest(operation),
params;
request.setConfig({
scope : me,
callback : me.createRequestCallback(request, operation),
disableCaching : false // explicitly set it to false, ServerProxy handles caching
});
return me.sendRequest(request);
},
sendRequest: function(request) {
var input = request.getOperation().getParams().query;
if(input) {
this.autocompletePlaceService.getPlacePredictions({
input: input
}, request.getCallback());
} else {
// don't query Google with null/empty input
request.getCallback().apply(this, [new Array()]);
}
this.lastRequest = request;
return request;
},
abort: function(request) {
// not supported by Google API
},
createRequestCallback: function(request, operation) {
var me = this;
return function(places) {
// handle result from google API
if (request === me.lastRequest) {
me.lastRequest = null;
}
// turn into a "response" ExtJs understands
var response = {
status: 200,
responseText: places ? Ext.encode(places) : []
};
me.processResponse(true, operation, request, response);
};
},
destroy: function() {
this.lastRequest = null;
this.callParent();
}
});
Note: I wrote this against ExtJs6 but it should basically work alike for ExtJs4.

List and store binding... exact same data

I am using sencha to create a carousel which has multiple card panels. Each panel contains a list component that is attached to its own instance of a store.
All lists store instances call the same API to fetch the data but with different parameters.
Example:
Card 1, Has list 1 attached to Store 1 which calls mywebsite.com/api?node=1
Card 2, Has list 2 attached to Store 2 which calls mywebsite.com/api?node=2
Card 1 shows the right set of nodes retrieved from the API. But once i swipe to see card 2, both list 1 and list 2 show the exact same data although each one should have its own list od data.
Code:
Test.data.NodeStore = Ext.extend(Ext.data.Store, {
constructor : function(config) {
config = Ext.apply({
model: 'Test.models.Node',
autoLoad: false,
pageSize: 20,
proxy: {
type: 'scripttag',
url: Test.API.URL + '?action=getNodes',
extraParams: {
},
reader: {
type: 'json'
}
},
setSource: function(source) {
if(this.getProxy().extraParams.sourceID != source) {
this.getProxy().extraParams.sourceID = source;
}
}
}, config);
Test.data.NodeStore.superclass.constructor.call(this, config);
},
onDestroy : function(config) {
Test.data.NodeStore.superclass.onDestroy.apply(this, arguments);
}
});
Ext.reg('NodeStore', Test.data.NodeStore);
The list view:
Test.views.ListView = Ext.extend(Ext.Panel, {
sourceID: 0,
layout: {
type: 'vbox',
align: 'stretch'
},
items: [
{
xtype: 'list',
itemTpl : new Ext.XTemplate("<div class='node'>{title}</div>"),
store: Ext.create(Test.data.NodeStore, {}),
}
],
setSource: function(source) {
this.sourceID = source;
var store = this.items.get(0).getStore();
store.setSource(source);
store.load();
}
});
The main view which creates list views dynamically
Test.views.Viewer = Ext.extend(Ext.Carousel, {
indicator: false,
layout: 'card',
style: {
padding: '0 20px'
},
items: [
],
loadListView: function(listIndex) {
var currentRecord = Test.stores.ListStore.getAt(listIndex);
var newList = new Test.views.ListView();
newList.setSource(currentRecord.get('ID'));
this.add(newList);
this.doLayout();
},
initComponent: function() {
Test.views.Viewer.superclass.initComponent.apply(this, arguments);
loadListView(1);
loadListView(2);
}
});
This is really wierd... i am just wondering, is sencha assigning the exact same store, model, list component... don't know where to look
In the loadListView function, i had to create an object of store and assign it to the list dynamically rather than modifying existing store.
newList.items.get(0).store = Ext.create(Test.data.NodeStore, {});

How do I stop ext-js from adding limit=25 to my JSON query?

The following code is working. The problem is the request is being sent with &_dc=1299207914646&limit=25 appended to every request sent to the server. Nothing I can do changes the limit=25. Ideally I want no additional parameters sent to the server. I would make do however with being able to set the limit to 10000 or something. I AM able to add other parameters but nothing I do removes the limit=25. I would also like to get rid of the &_dc parameter although I don't know why it has been added it is not causing a problem.
Any ideas?
note: some weird problem with code formatting below?
Thanks
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.panel.*'
]);
Ext.onReady(function(){
Ext.regModel('Image_', { // window.Image is protected in ie6 !!!
fields: ['id', 'key', 'value']
});
var store = new Ext.data.JsonStore({
model: 'Image_',
proxy: {
type: 'ajax',
var store = new Ext.data.JsonStore({
model: 'Image_',
proxy: {
type: 'ajax',
autoload: 'false',
url: '/couchdb/test/_design/blah/_view/by_surname2?startkey=%22r%22&endkey=%22r\u9999%22',
reader: {
type: 'json',
root: 'rows'
}
}
});
store.load();
var listView = new Ext.grid.GridPanel({
width:425,
height:250,
collapsible:true,
title:'Simple ListView <i>(0 items selected)</i>',
renderTo: Ext.getBody(),
store: store,
multiSelect: true,
viewConfig: {
emptyText: 'No images to display'
},
headers: [{
text: 'File',
flex: 50,
dataIndex: 'value'
},{
text: 'Last Modified',
flex: 35,
dataIndex: 'key'
},{
text: 'Size',
dataIndex: 'id',
flex: 15,
cls: 'listview-filesize'
}]
});
// little bit of feedback
listView.on('selectionchange', function(view, nodes){
var l = nodes.length;
var s = l != 1 ? 's' : '';
listView.setTitle('Simple ListView <i>('+l+' item'+s+' selected)</i>');
});
});
In your Proxy, set
limitParam: undefined,
pageParam: undefined,
startParam: undefined,
noCache: false,
You can modify your store limit when you load the store.
store.load({params:{limit:50}});
In this case, I am asking to set the limit to 50.
_dc=1299207914646 is unique cache-buster param added to GET requests. If you don't want to have them in the url, you can disable them by setting disableCaching parameter to false.
But I would recommend you to set the method of you store to POST and pass the parameters using POST rather than GET method. That way you can have clean URLs and also hide the data being sent.
You can override getParams method of the Ext.data.proxy.Server.
For example, in my project I added custom boolean parameter embeddedParams and if I dont want to add ExtJS parameters to a request I set it to false in a store proxy:
/**
* Added embeddedParams option
*/
Ext.define('Ext.lib.overrides.ServerProxy', {
override: 'Ext.data.proxy.Server',
/**
* Add or not pagination, grouping, sorting and filtering parameters to the request. Defaults to true.
*/
embeddedParams: true,
/**
* #private
* Copy any sorters, filters etc into the params so they can be sent over the wire
*/
getParams: function (operation) {
var me = this,
params = {},
isDef = Ext.isDefined,
groupers = operation.groupers,
sorters = operation.sorters,
filters = operation.filters,
page = operation.page,
start = operation.start,
limit = operation.limit,
simpleSortMode = me.simpleSortMode,
simpleGroupMode = me.simpleGroupMode,
pageParam = me.pageParam,
startParam = me.startParam,
limitParam = me.limitParam,
groupParam = me.groupParam,
groupDirectionParam = me.groupDirectionParam,
sortParam = me.sortParam,
filterParam = me.filterParam,
directionParam = me.directionParam,
hasGroups, index;
if (me.embeddedParams && pageParam && isDef(page)) {
params[pageParam] = page;
}
if (me.embeddedParams && startParam && isDef(start)) {
params[startParam] = start;
}
if (me.embeddedParams && limitParam && isDef(limit)) {
params[limitParam] = limit;
}
hasGroups = me.embeddedParams && groupParam && groupers && groupers.length > 0;
if (hasGroups) {
// Grouper is a subclass of sorter, so we can just use the sorter method
if (simpleGroupMode) {
params[groupParam] = groupers[0].property;
params[groupDirectionParam] = groupers[0].direction || 'ASC';
} else {
params[groupParam] = me.encodeSorters(groupers);
}
}
if (me.embeddedParams && sortParam && sorters && sorters.length > 0) {
if (simpleSortMode) {
index = 0;
// Group will be included in sorters, so grab the next one
if (sorters.length > 1 && hasGroups) {
index = 1;
}
params[sortParam] = sorters[index].property;
params[directionParam] = sorters[index].direction;
} else {
params[sortParam] = me.encodeSorters(sorters);
}
}
if (me.embeddedParams && filterParam && filters && filters.length > 0) {
params[filterParam] = me.encodeFilters(filters);
}
return params;
}
});
Usage:
store: Ext.create('Ext.data.Store', {
...
proxy: {
...
type: 'ajax', // or 'direct', 'jsonp' / 'scripttag'
embeddedParams: false
}
})
add the limit property to your store...
limit:50,
and might not hurt to try pagesize....
pagesize:50
and see if either of these help.
Edit : also try
pageParam:undefined,
in your proxy.
found that last piece from...
http://www.sencha.com/forum/showthread.php?118445-CLOSED-1.0.1-Ext.data.JsonStore-quot-limit-quot-param-issue
You can modify the limit param using
store.proxy.limitParam=null;
To remove the _dc parameter on extjs 4 you can set:
noCache: false
or just uncheck the box if you're using architect 2.
Specifically for Json, to get rid of _dc parameter, in your proxy object, set the config option given by Tharahan:
proxy: {
type: 'ajax',
api: {
read: 'app/data/something.json',
update: 'app/data/something.json'
},
reader: {
type: 'json',
...
},
writer: {
type: 'json',
...
},
noCache: false
}
EDIT: (sorry, I did not look at the post date, but lost so much time with it) Please note that the global Ext.Loader.setConfig({disableCaching: false}); does not affect subclasses of Ext.data.proxy.Server which need this specific option (at least in development with sencha touch 2.2.0).

extJS - Can not get data to render in GridPanel

The below code uses Ext.data.Store to retrieve a JSON with table metadata (for the column headings) and the table's data. The backend PHP script is working correctly and the Ext.data.Store contains valid records for the data - I just can't get them to go "into" the Grid itself.
The API Documentation makes it seem as if I just define a store property for Ext.grid.GridPanel and it will handle the rest.
Note: The code below is a separate from the rest of the application. We have pulled this portion out to see if we can just get a grid working, without the influence of the rest of the application.
Ext.BLANK_IMAGE_URL = 'js/ext/resources/images/default/s.gif';
Ext.onReady(function() {
var columns = [];
var fields = [];
var tabPanel = new Ext.TabPanel({
renderTo: Ext.getBody(),
activeTab: 0,
height: 700
});
var queryHeaders = Ext.data.Record.create([
{name: 'id'},
{name: 'table'},
{name: 'field'},
{name: 'title'}
]);
var applicationStore = new Ext.data.Store({
autoLoad: true,
reader: new Ext.data.JsonReader({root: 'fields'}, queryHeaders),
url: 'http://localhost/aargh/index.php/applications/hardware',
listeners: {
'load': function() {
console.info(applicationStore);
applicationStore.each(function(r) {
this_column = [];
this_column['header'] = r.data['title'];
this_column['dataIndex'] = r.data['id'];
columns.push(this_column);
this_column = []
this_column['name'] = r.data['id'];
fields.push(this_column);
});
console.info(fields);
var queryFields = Ext.data.Record.create([fields]);
var queryStore = new Ext.data.Store({
autoLoad: true,
reader: new Ext.data.JsonReader({root: 'fields'}, queryFields),
url: 'http://localhost/aargh/index.php/query/execute/applications/hardware',
listeners: {
'load': function() {
console.info(queryStore);
tabPanel.add(new Ext.grid.GridPanel({
title: 'Hardware',
store: queryStore,
columns: columns,
autoHeight: true,
frame: true
}));
tabPanel.doLayout();
}
}
});
}
}
});
});
As I review the applicationStore and queryStore objects in Firebug I can see the expected data results perfectly in applicationStore.data.items.#.json and queryStore.data.items.#.json (of course, replacing # with the record number).
Any ideas?
Wow - this has been giving us trouble for three days. Turns out I was making an array within an array at var queryFields = Ext.data.Record.create([fields]);
Changing that to: var queryFields = Ext.data.Record.create(fields); fixed the issue.

Categories