Custom proxies on Stores and Models seems inconsistent (and does not work on Models) - zend-framework

Am using Extjs 4, and have created a custom Rest Proxy to handle communication with my Zend backend api.
(See post http://techfrere.blogspot.com/2011/08/linking-extjs4-to-zend-using-rest.html)
When using a Store to handle communication, I was using Ext.require to load the proxy, and then referenced the proxy on the type field and all was good and it loaded my data: as per:
Ext.require('App.utils.ZendRest');
...
proxy : {
type : 'zest', // My custom proxy alias
url : '/admin/user'
...
}
I then decided to try to use the proxy directly on a model... and no luck. The above logic does not work.
Problems
1. When referencing zest, it does not find the previously loaded ZendRest class (aliased to proxy.zest)
2. It tries to load the missing class from App.proxy.zest (which did not exist.)
So I tried moving my class to this location and renaming to what it seemed to want. No luck.
It loads the class, but still does not initialize the app... I get no errors anywhere so v difficult to figure out where the problem is after this...
For now it seems I will have to revert to using my Zend Rest proxy always via the Store.
Question is... has anyone else seen the behavior? Is it a bug, or am I missing something?
Thanks...

Using your proxy definition, I've managed to make it work.
I am not sure why it doesn't work for you. I have only moved ZendRest to Prj.proxy namespace and added requires: ['Prj.proxy.ZendRest'] to the model.
Code:
// controller/Primary.js
Ext.define('Prj.controller.Primary', {
extend: 'Ext.app.Controller',
stores: ['Articles'],
models: ['Article'],
views: ['article.Grid']
});
// model/Article.js
Ext.define('Prj.model.Article', {
extend: 'Ext.data.Model',
fields: [
'title', 'author', {
name: 'pubDate',
type: 'date'
}, 'link', 'description', 'content'
],
requires: ['Prj.proxy.ZendRest'],
proxy: {
type: 'zest',
url: 'feed-proxy.php'
}
});
// store/Articles.js
Ext.define('Prj.store.Articles', {
extend: 'Ext.data.Store',
autoLoad: true,
model: 'Prj.model.Article'
});
// proxy/ZendRest.js
Ext.define('Prj.proxy.ZendRest', {
extend: 'Ext.data.proxy.Ajax',
alias : 'proxy.zest',
appendId: true,
batchActions: false,
buildUrl: function(request) {
var me = this,
operation = request.operation,
records = operation.records || [],
record = records[0],
format = me.format,
reqParams = request.params,
url = me.getUrl(request),
id = record ? record.getId() : operation.id;
if (me.appendId && id) {
if (!url.match(/\/$/)) {
url += '/';
}
url += 'id/' + id;
}
if (format) {
reqParams['format'] = format;
}
/* <for example purpose> */
//request.url = url;
/* </for example purpose> */
return me.callParent(arguments);
}
}, function() {
Ext.apply(this.prototype, {
actionMethods: {
create : 'POST',
read : 'GET',
update : 'PUT',
destroy: 'DELETE'
},
/* <for example purpose> */
reader: {
type: 'xml',
record: 'item'
}
/* </for example purpose> */
});
});
Here is working sample, and here zipped code.

Related

Use DataFields in Rest URL in ExtJS to access Context.io API

I have two Question Regarding Rest API in EXTJS.
How can I use fields to make rest URL dynamic?
How can I add authentication key to access Context.io in my Rest.Proxy?
This is my solution, but I am not sure if I have done it properly, or not. I am pretty new in ExtJS, so my question may be basic, but I appreciate your help.
Ext.define("EmailFolders", {
extend: "Ext.data.Model",
fields: ["id", "label"],
proxy: {
type: "rest",
url: "lite/users/:" + id + "/email_accounts/:" + label + "/folders"
},
reader: {
type: "json"
},
headers: {
CONSUMER_KEY: "KEY FROM CONTEX.IO",
CONSUMER_SECRET: "SECRET FROM CONTEXT.IO"
}
});
You could use store.getProxy() to make rest URL dynamic and to pass the authentication keys in headers. Proxy have methods
proxy.setUrl() to sets the value of url.
proxy.setHeaders() to sets the value of headers.
You can check here with working fiddle
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
let url = 'https://jsonplaceholder.typicode.com/users';
// Set up a model to use in our Store
Ext.define('User', {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
reader: {
type: 'json',
rootProperty: ''
}
}
});
Ext.define('MyStore', {
extend: 'Ext.data.Store',
model: 'User',
listeners: {
beforeload: function (store) {
var proxy = store.getProxy();
//if you want, you can also set here url inside of beforeload
//proxy.setUrl(url);
/*
* You can use {proxy.setHeaders} to set the values from CONTEX.IO
* After ajax request see your request parameter in network analysis below 2 headers are passed in request header
*/
proxy.setHeaders({
CONSUMER_KEY: "KEY FROM CONTEX.IO",
CONSUMER_SECRET: "SECRET FROM CONTEXT.IO"
});
}
}
});
let store = new MyStore();
//Set the dynamic url here
//This {url} will be dynamic whatever you want to pass
store.getProxy().setUrl(url);
store.load(function (data) {
console.log(data);
alert('Open console to see reposne..!')
});
/*
You can also pass url inside of load funtion
*/
new MyStore().load({
url: url + '/' + 1,
callback: function (data) {
console.log(data);
}
});
}
});

how to sync data from ydn-db web app to backend server?

With ydn-dn, i want to automatically synchronise data from my web app with my REST back end.
I read the documentation and searched in examples but i cannot make it work.
https://yathit.github.io/ydn-db/synchronization.html
http://dev.yathit.com/api/ydn/db/schema.html#sync
I tried to define a schema with sync configuration like that :
var schema = {
stores: [ {
name: 'contact',
keyPath: 'id',
Sync: {
format: 'rest',
transport: service,
Options: {
baseUri: '/'
}
}
}
]
};
and created a function for transport :
var service = function(args) {
console.log("contact synch");
};
but my service function is never called.
I certainly misunderstood how YDN-db work, but i didn't found any example.
To complete, here is a jsfiddle :
http://jsfiddle.net/asicfr/y7sL7b3j/
Please see the example http://yathit.github.io/ydndb-demo/entity-sync/app.html
Older example http://yathit.github.io/sprintly-service/playground.html from https://github.com/yathit/sprintly-service

Ext.Direct File Upload - Form submit of type application/json

I am trying to upload a file through a form submit using Ext.Direct, however Ext.direct is sending my request as type 'application/json' instead of 'multipart/form-data'
Here is my form.
{
xtype: 'form',
api: {
submit: 'App.api.RemoteModel.Site_Supplicant_readCSV'
},
items: [
{
xtype: 'filefield',
buttonOnly: false,
allowBlank: true,
buttonText: 'Import CSV'
}
],
buttons:
[
{
text: 'Upload',
handler: function(){
var form = this.up('form').getForm();
if(form.isValid()){
form.submit({
waitMsg: 'Uploading...',
success: function(form, action){
console.log(action.result);
}
});
}
}
}
]
},
On the HTTP request, it checks to see if the request options is a form upload.
if (me.isFormUpload(options)) {
which arrives here
isFormUpload: function(options) {
var form = this.getForm(options);
if (form) {
return (options.isUpload || (/multipart\/form-data/i).test(form.getAttribute('enctype')));
}
return false;
},
getForm: function(options) {
var form = options.form || null;
if (form) {
form = Ext.getDom(form);
}
return form;
},
However, options looks like this
{
callback: function (options, success, response) {
jsonData: Object
action: "RemoteModel"
data: Array[1]
0: form
length: 1
__proto__: Array[0]
method: "Site_Supplicant_readCSV"
tid: 36
type: "rpc"
__proto__: Object
scope: constructor
timeout: undefined
transaction: constructor
}
And there is no direct form config, but it exists in jsonData.data[0]. So it doesn't set it as type multipart/form-data and it gets sent off as type application/json.
What am I doing wrong? Why isn't the form getting submitted properly?
Edit - I am seeing a lot of discussion about a 'formHandler' config for Ext.Direct? I am being led to assume this config could solve my issue. However I don't know where this should exist. I'll update my post if I can find the solution.
Solution - Simply adding /formHandler/ to the end of the params set the flag and solved my issue. Baffled.
Supplicant.prototype.readCSV = function(params,callback, request, response, sessionID/*formHandler*/)
{
var files = request.files;
console.log(files);
};
The method that handles file upload requests should be marked as formHandler in the
Ext.Direct API provided by the server side.
EDIT: You are using App.api.RemoteModel.Site_Supplicant_readCSV method to upload files; this method needs to be a formHandler.
I'm not very familiar with Node.js stack but looking at this example suggests that you may need to add /*formHandler*/ descriptor to the function's declaration on the server side.

sencha touch rest proxy url

Why if a use a JSON file foo.json my code works but if I change the URL to something.com/foo.json it doesn´t work?
This is working in my project:
var store = Ext.create('Ext.data.Store', {
model: 'Client',
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
url : 'clients.json',
reader: {
type: 'json'
}
}
});
What I want is to replace the static file for an URL:
var store = Ext.create('Ext.data.Store', {
model: 'Client',
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
url : 'http://rails-api.herokuapp.com/clients.json',
reader: {
type: 'json'
}
}
});
The clients.json file is a copy/paste from http://rails-api.herokuapp.com/clients.json it is the same data.
Where do you run your application? Are you able to track the http requests? Do you get any output on your javascript console?
If i had to guess I'd say that your issue might be related to CORS => http://en.wikipedia.org/wiki/Cross-origin_resource_sharing.
Edit:
Note that you only need to have a look at CORS or use jsonp if you are running your app and the "backend"/api on two different webservers.
Most people will probably...
a) ...run the app on the same webserver as the backend or...
b) ...use native packaging (cordova, phonegap or sencha cmd s own packaging).
In both cases you can simply use the "normal" ajax or rest proxys.
On the server side I had to add the callback, see this question sencha-seems-to-not-like-rails-json also I had to change the type from rest to jsonp and removed some useless code, at the end my code looks like this:
var store = Ext.create('Ext.data.Store', {
model: 'Client',
autoLoad: true,
autoSync: true,
proxy: {
type: 'jsonp',
url : 'http://rails-api.herokuapp.com/clients.json'
}
});
on the server side:
def index
#clients = Client.all
respond_to do |format|
format.html
format.json { render :json => #clients, :callback => params[:callback] }
end
end

RESTful Model, get rid of the id query param in the GET request

I'm a little bit stuck here. My model code is
Ext.define('MyFancyModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'string' },
{ name: 'name', type: 'string' }
],
proxy: {
type: 'rest',
url: '/fancymodel',
noCache: false
}
});
When I try to load data by id using
Ext.ModelManager.getModel('MyFancyModel').load('some-id', {});
the request url is /fancymodel/some-id?id=some-id which is obviously not correct. So how can I achieve the right request url: /fancymodel/some-id without any patches or overrides?
EDIT:
jsfiddle
In the developer console you can see failed GET request
http://fiddle.jshell.net/fancymodel/some-id?id=some-id
EDIT:
Thread on the Sencha forum
I haven't found any ExtJS solution, so I have written a small patch (not sure it works in every situations) :
Ext.override(Ext.data.proxy.Rest, {
buildUrl: function (request) {
delete request.params.id;
return this.callParent(arguments);
}
});
The standard way :
Ext.define('MyPatches.data.proxy.Rest', {
override: 'Ext.data.proxy.Rest',
buildUrl: function (request) {
delete request.params.id;
return this.callParent(arguments);
}
});