Handling 404 exceptions in Sencha touch Store with an ajax proxy - exception

I'm trying to make my code a little more robust, by handling all sorts of exceptions that may occur. One may be a 404 exception on a Json web request. It looks like the callback method of store.load isn't called when the Json request gets a 404 exception.
The code:
Ext.regModel('Activiteit', {
fields: [
{ name: 'id', type: 'int' },
{ name: 'ServerId', type: 'int', mapping: 'Id' },
{ name: 'Title', type: 'string' },
{ name: 'Description', type: 'string' },
],
});
Ext.regApplication({
name: 'App',
launch: function () {
console.log('launch');
var ajaxActiviteitStore = new Ext.data.Store({
model: "Activiteit",
storeId: 'ajaxActiviteitStore',
proxy: {
type: 'ajax',
url: '/senchatest/Activiteit/Gett/',
reader: {
type: 'json',
root: 'activiteiten'
}
}
});
ajaxActiviteitStore.load(function (records, operation, success) {
//the operation object contains all of the details of the load operation
console.log(success);
});
}
});
This results in a "Uncaught TypeError: Cannot read property 'length' of undefined" exception on line 7212 of sencha-touch-debug.js. I'm using version 1.1.0 of sencha touch.
The stacktrace:
Uncaught TypeError: Cannot read property 'length' of undefined
Ext.data.Store.Ext.extend.loadRecords sencha-touch-debug.js:7212
Ext.data.Store.Ext.extend.onProxyLoad sencha-touch-debug.js:7024
(anonymous function) sencha-touch-debug.js:8742
Ext.data.Connection.Ext.extend.onComplete sencha-touch-debug.js:17566
Ext.data.Connection.Ext.extend.onStateChange sencha-touch-debug.js:17513
(anonymous function) sencha-touch-debug.js:3421
What am I doing wrong here?
I found a workaround by adding a listener to the proxy that listens to the 'exception' event, but I'd rather like the callback function of the store load to be called. Am I doing something wrong, or is this default behaviour?
Thanks,
Sander

I encounter the same Exception (Uncaught TypeError: Cannot read property 'length' of undefined) with an AjaxProxy (ST 1.1.0) if the server return an error (404, 500, ...).
Actually, I think the problem is in the Ext.data.AjaxProxy.createRequestCallback method.
I solved my problem with a dirty code like this:
var ajaxActiviteitStore = new Ext.data.Store({
model: "Activiteit",
storeId: 'ajaxActiviteitStore',
proxy: {
type: 'ajax',
url: 'some nonexistent url',
reader: {
type: 'json',
root: 'activiteiten'
},
listeners: {
exception: function(store, response, op) {
console.log('Exception !');
// hack to avoid js exception :
// TypeError: 'undefined' is not an object (evaluating 'records.length')
// on line sencha-touch-debug-1-1-0.js:7212
op.records = [];
}
}
}
});
Hope this can help, and I will look to open an issue on sencha-touch forum.

I think you have another problem that unexisted url. Nevertheless, try this:
var storeException = 0;
this.ajaxActiviteitStore = new Ext.data.Store({
model: "Activiteit",
storeId: 'ajaxActiviteitStore',
proxy: {
type: 'ajax',
url: 'some nonexistent url',
reader: {
type: 'json',
root: 'activiteiten'
},
listeners: {
exception: {
fn: function(proxy, response, operation ) {
// you can parse `response.responseText` to make some decisions
storeException = 404;
}
}
}
}
});
this.ajaxActiviteitStore.load({
scope: this,
callback: function (records, operation, success) {
if (storeException==0) {
// do something
} else {
alert('Service unaviable');
}
}
});

Related

When function is called from observer, error that “TypeError ... is not a function” happens

When function is called from observer, error that “TypeError ... is not a function” happens:
selected_project_id : {
type: Number,
observer: '_selected_project_idChanged'
},
...
_selected_project_idChanged(selected_project_id) {
this.some_function();
}
Uncaught TypeError: this.some_function is not a function at HTMLElement
Type of the parameter should be Object:
selected_project_id : {
type: Oblect,
observer: '_selected_project_idChanged'
},

ExtJs5: How to read server response in Model.save

I use Model.save to save data from the ExtJs form. Sometimes server returns operation status in following format:
{"success": false, "error": {"name": "Invalid Name"}}
The following code sends data from form to server:
var model = formPanel.getRecord();
model.save({
callback: function(record, operation, success) {
// operation.response is null,
// and success === true
// how to read server response here?
}
})
Server response is treated as successful because HTTP status is 200. So I I have to read server response to check operation status. But operation.response is null in callback function.
Here is my Model:
Ext.define('My.Model', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{name: 'id', type: 'auto'},
{name: 'name', type: 'auto'}
],
proxy: {
type: 'rest',
url: 'api/v1/models',
appendId: true,
reader: {
type: 'json',
},
writer: {
type: 'json'
}
}
});
Question: how can I access server response after Model.save's call?
More generic question: is it semantically correct to use Model.load or Model.save to populate/save the ExtJs form?
I'm using ExJs 5.0.1.1255.
I created some simple test code for this:
var Clazz = Ext.define('MyModel', {
extend: 'Ext.data.Model',
proxy: {
type: 'rest',
url: 'api/v1/models'
}
});
var instance = Ext.create('MyModel', {
name: 'MyName'
});
instance.save({
callback: function(record, operation) {
}
});
The server responds with:
{
success: true,
something: 'else'
}
You can see this in a fiddle here: https://fiddle.sencha.com/#fiddle/fhi
With this code, the callback has a record argument, and record.data contains the the original record merged with the server response. In addition, you can do operation.getResponse() (rather than just operation.response) to get full access to the server's response.
In regard to your question on load vs save, if you use view models and bind the model that way, it kind of becomes moot as your form should always reflect the state of the model.
Using model.save() and Model.load() is definitely the correct thing to do.
In addition to providing a custom callback, you should investigate configuring a custom proxy. In a custom proxy, you can provide your own implementation of the extractResponseData method. This would let you centralise your need to examine the server response.

Ember data - Cannot read property 'typeKey' of undefined

Trying to load a plan model, embedded, into my app model.
I keep getting the following error when loading (it saves just fine):
Cannot read property 'typeKey' of undefined TypeError: Cannot read property 'typeKey' of undefined
at Ember.Object.extend.modelFor (http://localhost:4200/assets/vendor.js:71051:22)
at Ember.Object.extend.recordForId (http://localhost:4200/assets/vendor.js:70496:21)
at deserializeRecordId (http://localhost:4200/assets/vendor.js:71500:27)
at http://localhost:4200/assets/vendor.js:71477:11
at http://localhost:4200/assets/vendor.js:69701:20
at http://localhost:4200/assets/vendor.js:17687:20
at Object.OrderedSet.forEach (http://localhost:4200/assets/vendor.js:17530:14)
at Object.Map.forEach (http://localhost:4200/assets/vendor.js:17685:14)
at Function.Model.reopenClass.eachRelationship (http://localhost:4200/assets/vendor.js:69700:42)
at normalizeRelationships (http://localhost:4200/assets/vendor.js:71463:12) vendor.js:17062logToConsole
With that said I have the following models,
app/models/app.js
export default DS.Model.extend({
name: attribute('string'),
domain: attribute('string'),
plan: DS.belongsTo('plan', { embedded: 'load' }),
creator: DS.belongsTo('user', { async: true }),
time_stamp: attribute('string', {
defaultValue: function () {
return moment().format("YYYY/MM/DD HH:mm:ss");
}
})
});
app/models/plan.js
export default DS.Model.extend({
price: attribute('number'),
description: attribute('string'),
tagline: attribute('string'),
title: attribute('string'),
features: attribute('array') // Array is defined in a transform, don't worry.
});
Plan being kind of a static document.
Here's my server response when calling store.get('creator.apps');
{
"apps":[
{
"_id":"53da9994b2878d0000a2e68f",
"name":"Myapp",
"domain":"http://myapp.com",
"creator":"53d9598bb25244e9b1a72e53",
"plan":{
"_id":"53d93c44b760612f9d07c921",
"price":0,
"description":"Free plan",
"tagline":"Great for testing",
"title":"Developer",
"features":["5,000 Requests","API/Plugin Access"],
"__v":0
},
"time_stamp":"2014/07/31 13:31:32",
"__v":0
}
]
}
I realize that the typeKey error is due to Ember not finding a model for the response. I can confirm that it finds the app type, firing a hook under normalizeHash.apps.
Sorry this is such a long post, just can't wrap my head around the cause of the issue!
App.Thing = DS.Model.extend(
{
name: attr('string'),
children: DS.hasMany('child', {inverse:null})
}
);
App.ThingSerializer = DS.RESTSerializer.extend(
DS.EmbeddedRecordsMixin, {
attrs: {
children: { embedded: 'always' }
}
}
);
DS.EmbeddedRecordsMixin must be in your model and you must have `embedded:'always' for the correct attribute.
If you have a Thing model then you can make Ember Data load the embedded children (here and array of nested objects) by using the model specific serializer.
Resources:
http://emberjs.com/guides/models/customizing-adapters/
http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html
Ember doesn't want to have the record embedded in the JSON of the parent record.
Do what you need to, to get your json like this. With just the plan id.
{
"apps":[
{
"_id":"53da9994b2878d0000a2e68f",
"name":"Myapp",
"domain":"http://myapp.com",
"creator":"53d9598bb25244e9b1a72e53",
"plan_id":"53d93c44b760612f9d07c921", // just output id only not embedded record
"time_stamp":"2014/07/31 13:31:32",
"__v":0
}
]
}
This then lets ember look up the related model itself, using the async: true
export default DS.Model.extend({
name: attribute('string'),
domain: attribute('string'),
plan: DS.belongsTo('plan', { async: true }), //changed
creator: DS.belongsTo('user', { async: true }),
time_stamp: attribute('string', {
defaultValue: function () {
return moment().format("YYYY/MM/DD HH:mm:ss");
}
})
});
I've just gone through the pain of this myself and with some help found an answer.
For anyone else who's come here and still is has issues, read my answer to my own question for a detailed rundown of what the typeKey error means and further steps I used to resolve the issue myself.
Deploying ember-rails to Heroku - TypeError: Cannot read property 'typeKey' of undefined

ExtJS 4 store and manage record

I have a question about extjs 4.
Below is my storeMsg
var storeMsg = this.getMessageStore();
storeMsg.load({
scope: this,
autoLoad: true,
params:{
read_conditions: Ext.JSON.encode({
"employee_rid": '7976',
"year" : '2013', //etos
"kind_holiday_rid" : '1',
"request_days" : '5'
})
},
callback: function(records, operation, success) {
// do something after the load finishes
console.log(records[0].get('remain'));
console.log(records[0].get('messages'));
}
});
and i take a json response like as
{"total":1,"success":true,"data":[{"status":"true","messages":"\u03a3\u03c9\u03c3\u03c4\u03cc \u03b1\u03af\u03c4\u03b7\u03bc\u03b1 \u03ac\u03b4\u03b5\u03b9\u03b1\u03c2","remain":"25"}]}
I want to take the field status from json (ex true) outside from storeMsg.load();
For example
var vstatus = Ext.StoreMgr.lookup(storeMsg).data.items[0].data.status
but i take message this vstatus is undefined
I have changed my variable (vstatus) of code :
var vstatus = Ext.StoreMgr.lookup(storeMsg).getProxy().getReader();
and I am taking and object like as
className "Ext.data.reader.Json"
and it has some attributes. An attribute is
jsonData
data
remain 25
status true
message "Is correct"
total 1
success true
and I give in
var vstatus = Ext.StoreMgr.lookup(storeMsg).getProxy().getReader().jsonData;
and I take this message (undefined).
Do you have any idea how take the value from jsonData.data.status = true;
tnx
and the fully code about store , proxy and reader is below
Ext.define('MHR.store.Message',{
extend : 'Ext.data.Store',
model : 'MHR.model.Message',
storeId : 'Message',
autoLoad : true,
proxy : {
type: 'ajax',
api: {
read : 'php/crud.php?action=check'
},
actionMethods: {
read : 'POST',
},
reader: {
type: 'json',
root: 'data',
rootProperty: 'data',
successProperty: 'success',
messageProperty: 'message'
},
extraParams : {
'read_conditions': ''
}
}
});
try with:
storeMsg.each(function(record) {
var status = record.get('status');
});

Accessing nested objects in JSON feed - Sencha Touch

I'll begin with the usual disclaimer: new to Sencha Touch/working with JSON, floundering in the dark. Any help or prodding in the right direction is appreciated more than you know!
I'm trying to get my app to fetch data from a public Google Spreadsheet JSON feed. From what I've managed to figure out, my current model is based on JSON arrays, NOT nested objects. How do I access and return a nested object?
Ext.regModel('Count', {
fields: [{name:'$t'}]
});
this.list = new Ext.List({
itemTpl: new Ext.XTemplate('<div>{$t}</div>'),
loadingText: false,
store: new Ext.data.Store({
model: 'Count',
proxy: {
type: 'scripttag',
url : 'http://spreadsheets.google.com/feeds/cells/0AuYDRk91MX8-dHhkV29ZVkRGNjlvZjV4QVBIVmJubVE/odb/public/basic?range=A1&alt=json',
reader: {
type: 'json',
root: 'feed'
}
}
})
});
The JSON data (extra stuff removed, above link will show all of it if need be, contains an email address I'd rather not post and have indexed):
{
"feed":{
"entry":[{
"content":{
"type":"text",
"$t":"11"
}
}]
}
}
If I plop in another JSON feed that uses arrays I can work with it just fine, but just can't figure out what I need to do to access that integer in the object that corresponds to $t. If I put "entry" as the root instead of "feed," I get an error that reads, "Uncaught TypeError: Cannot read property 'length' of undefined."
The solution! Turns out Sencha didn't like the $ in my template variable.
Ext.regModel('Count', {
fields: [{name:'count', mapping:'content.$t'}]
});
this.list = new Ext.List({
itemTpl: new Ext.XTemplate('<div>{count}</div>'),
loadingText: false,
store: new Ext.data.Store({
model: 'Count',
proxy: {
type: 'scripttag',
url : 'http://spreadsheets.google.com/feeds/cells/0AuYDRk91MX8-dHhkV29ZVkRGNjlvZjV4QVBIVmJubVE/odb/public/basic?range=A1&alt=json',
reader: {
type: 'json',
root: 'feed.entry'
}
}
})
});