sencha touch rest proxy url - rest

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

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);
}
});
}
});

OData Jaydata - odata update request returns error 404 (SAPUI5, node)

I'm building a web application with SAPUI5 which makes available a list of services, that are stored in a MongoDB and available as OData.
I followed this guide jaydata-install-your-own-odata-server-with-nodejs-and-mongodb and these are my model.js:
$data.Class.define("marketplace.Service", $data.Entity, null, {
Id: {type: "id", key: true, computed: true, nullable: false},
Name: {type: "string", nullable: false, maxLength: 50},
}, null);
$data.Class.defineEx("marketplace.Context", [$data.EntityContext, $data.ServiceBase], null, {
Services: {type: $data.EntitySet, elementType: marketplace.Service}
});
exports = marketplace.Context;
and server.js:
var c = require('express');
require('jaydata');
window.DOMParser = require('xmldom').DOMParser;
require('q');
require('./model.js');
var app = c();
app.use(c.query());
app.use(c.bodyParser());
app.use(c.cookieParser());
app.use(c.methodOverride());
app.configure(function() {app.use(app.router);});
app.use(c.session({secret: 'session key'}));
app.use("/marketplace", $data.JayService.OData.Utils.simpleBodyReader());
app.use("/marketplace", $data.JayService.createAdapter(marketplace.Context, function (req, res) {
return new marketplace.Context({
name: "mongoDB",
databaseName: "marketplace",
address: "localhost",
port: 27017
});
}));
app.use("/", c.static(__dirname));
app.use(c.errorHandler());
app.listen(8080);
The client is developed by using SAPUI5 and these are the parts of the code relative to the odata model creation:
oModel = sap.ui.model.odata.ODataModel("http://localhost:8080/marketplace", false); // connection to the odata endpoint
oModel.setDefaultBindingMode(sap.ui.model.BindingMode.TwoWay);
sap.ui.getCore().setModel(oModel);
The various services are correctly showed in a SAPUI5 table and I'm easily able to insert a new service by using the POST OData.request in this way:
OData.request({
requestUri: "http://localhost:8080/marketplace/Services",
method: "POST",
data: newEntry // json object with the new entry
},
function(insertedItem) {
// success notifier
},
function(err) {
// error notifier
}
);
and delete a service by using the SAPUI5 function oModel.remove() in this way (oParams is a json object which contains the alert notification functions):
var serviceId = oTable.getRows()[selectedIndex].getCells()[0].getText();
oModel.remove("/Services('" + serviceId + "')", oParams);
Everything works fine but the update request for a single service. I've tried with the functions provided by SAPUI5 (oModel.update or oModel.submitChanges), by using OData.request ("method: PUT"), by creating an ajax PUT request, I also tried to craft PUT request with Fiddler.
I always get error 404:
Request URL:http://localhost:8080/marketplace/Services('NTMzZDM3M2JlNjY2YjY3ODIwZjlmOTQ0')
Request Method:PUT
Status Code:404 Not Found
Where can be the problem?
I tried with Chrome, IE, and Firefox; same problem...
Thanks
Try to update with MERGE verb and pass the modified fields in JSON format inside the BODY

How to implement ReST services with Sails.js?

I am quite new to Node. I came across Sails.js. I think it is based on WebSocket, which seems to be really good for building real-time applications. I would like to know that whether Sails can be used to implement REST architecture as it uses WebSocket? And if yes, how?
Yes it can. Sails JS allows you to easily build a RESTful API, essentially with no effort to get started. Also, websockets (through socket.io) are integrated by default into the view and api.
To create a fully RESTful app from the ground up, it actually requires no JS. Try:
sails new testapp
cd testapp
sails generate model user
sails generate controller user
cd <main root>
sails lift
The CRUD (Create, Read, Update, Delete) actions are already created for you. No code!
You can create a user in your browser by doing the following:
HTTP POST (using a tool like PostMan) to http://:1337/user/create
{
"firstName": "Bob",
"lastName": "Jones"
}
Next, do a GET to see the new user:
HTTP GET http://:1337/user/
FYI - Sails JS uses a default disk based database to get you going
Done.
sails new testapp
cd testapp
sails generate api apiName
controller
create: function (req, res) {
var payload = {
name:req.body.name,
price:req.body.price,
category:req.body.category,
author:req.body.author,
description:req.body.description
};
Book.create(payload).exec(function(err){
if(err){
res.status(500).json({'error':'something is not right'})
}else{
res.status(200).json({'success':true, 'result':payload, 'message':'Book Created success'})
}
});
},
readone: async function (req, res) {
var id = req.params.id;
var fff = await Book.find(id);
if(fff.length == 0){
res.status(500).json({'error':'No record found from this ID'})
}else{
res.status(200).json({'success':true, 'result':fff, 'message':'Record found'})
}
},
model
attributes: {
id: { type: 'number', autoIncrement: true },
name: { type: 'string', required: true, },
price: { type: 'number', required: true, },
category: { type: 'string', required: true, },
author: { type: 'string' },
description: { type: 'string' },
},
routes
'post /newbook': 'BookController.create',
'get /book/:id': 'BookController.readone',

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);
}
});

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

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.