How to get a hasOne model with sencha touch - sencha-touch

I have a model Banner and a model BannerFormat. A banner has a banner format. To configure a hasOne relationship between banner and banner format, i wrote this :
Ext.define('admin.model.Banner', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'int' },
{ name: 'banner_format_id', type: 'int' },
'code',
'active',
'start_at',
'end_at'
],
associations: { type: 'hasOne', model: 'admin.model.BannerFormat', getterName: 'getBannerFormat' },
proxy: {
type: 'ajax',
url: '/admin/api_query.php',
extraParams: {
table: 'content_banners',
type: 'GET'
}
}
}
});
And in my bannerFormat model:
Ext.define('admin.model.BannerFormat', {
extend: 'Ext.data.Model',
config: {
fields: ['id', 'format'],
associations: { type: 'hasMany', model: 'admin.model.Banner' },
proxy: {
type: 'ajax',
url: '/admin/api_query.php',
extraParams: {
table: 'content_banner_formats',
type: 'GET'
}
}
}
});
But when i call banner.getBannerFormat(), i got :
Uncaught TypeError: Object [object Object] has no method 'getBannerFormat'
What did i go wrong?

Are you creating a banner object and then making the call on it to retrieve the defined associations?
This should work for you:
var banner = Ext.create('admin.model.Banner', {
id: 100,
banner_format_id: 20,
code: 'ABC123',
active: true,
start_at: 1,
end_at: 5
});
banner.getBannerFormat();
Also, you don't need to specify a getterName for the association if you don't want. Sencha will auto-generate a getter function for the association, which follows the format: 'getModelName'. If you removed the getterName from your association, the getter function on the banner model would be the same as what you defined it as: 'getBannerFormat';

Related

Extjs4 - Defining methods on a model

According to the docs, I should be able to define functions on a Model, and then call the function on instances of that model.
At least in the case where I load the model from a proxy, its not working.
My model:
Ext.define('MyApp.model.Detail', {
extend: 'Ext.data.Model',
fields: [
'someField',
'anotherField',
],
someFunction: function() {
//do something
},
proxy: {
type: 'ajax',
url: 'http://example.com/details',
reader: {
type: 'json',
root: 'data',
totalProperty: 'total',
successProperty: 'success',
}
},
});
Store:
Ext.define('MyApp.store.DetailStore', {
extend: 'Ext.data.Store',
storeId: 'detailStore',
model: 'MyApp.model.Detail',
});
Controller:
Ext.define('MyApp.controller.appController', {
extend: 'Ext.app.Controller',
init: function() {
this.getDetailStoreStore().addListener('load', this.newDetails, this);
},
stores: ['DetailStore'],
models: ['Detail'],
views : ['DetailView], //exists, not copied into question
newDetails: function(store, records) {
var details = records[0].data;
details.someFunction(); // Uncaught TypeError: Object #<Object> has no method 'someFunction'
}
});
The error happens in the newDetails function, when calling data.someFunction().
Do I have the wrong expectation?
The function exists on the model, so you would call:
records[0].someFunction();

Adding a AJAX response data to a store

How to add a data to a json store if my data is coming from a back end AJAX call.
my store is as follows .
Ext.define('MyApp.store.GeographyMasterStore', { extend: 'Ext.data.Store',
requires: [
'MyApp.model.GeographyMasterModel'
],
config: {
model: 'MyApp.model.GeographyMasterModel',
storeId: 'geographyMasterStore',
proxy: {
type: 'ajax',
reader: {
type: 'json'
}
}
}
});
And my model is as follows:
Ext.define('MyApp.model.GeographyMasterModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'Code'
},
{
name: 'Description'
},
{
name: 'Level_Code',
mapping: 'Level Code'
},
{
name: 'Name'
}
]
}
});
If I add the data like this
var geographyMasterStore = Ext.getStore('geographyMasterStore');
geographyMasterStore.add(<data from backend AJAX call>);
it does not show me the mapped field i.e. Level_Code
Usually I when add a record to the store like this :
Ext.create('App.model.MyModel', JSON.parse(response.responseText);
Where response is the response from an Ext.Ajax.request
Hope this helps
You need create a model:
var record = Ext.create('model.GeographyMasterModel', Ext.JSON.decode(response.responseText));
save the model:
record.save()
reload the store:
geographyMasterStore.load()

Populating Combobox from remote server

I have a combobox, i need to populate data from the server. In the server side i have the following data to be displayed.
PersonID
PersonFName
PersonLName
In the combobox, i need to display the text as PersonFName + PersonLName (Like James Smith- This is what it will display in the drop down) , and when a user selects a record, I need to display the corresponding PersonID (Like Person with PersonFName and PersonLName has the PersonID of 1) of that user.
I am unable to figure this out, here's my code
View :
{
xtype: 'combobox',
id: 'personcombo',
readOnly: false,
selectOnFocus: true,
forceSelection: true,
store: 'Person'
}
Store :
Ext.define('MyApp.store.PersonStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Person'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
model: 'MyApp.model.Person',
proxy: {
type: 'ajax',
api: {
read: 'person.php',
create: 'person.php'
},
reader: {
type: 'array'
}
}
}, cfg)]);
}
});
Model :
Ext.define('MyApp.model.Person', {
extend: 'Ext.data.Model',
fields: [
{
name: 'PersonID'
},
{
name: 'PersonFName'
},
{
name: 'PersonLName'
}
]
});
I think your question is: how to display PersonFName + PersonLName in the combobox but keep the PersonID field as the value.
You should add a converted field which joins the first and last names in your data model and then make that one your combobox displayField config.
Though the other answer did bring up a good point that the defined store in your combo is Person but you are showing code for a store named PersonStore.
It would look something like this:
Model:
Ext.define('MyApp.model.Person', {
extend: 'Ext.data.Model',
fields: [
{
name: 'PersonID'
},
{
name: 'PersonFName'
},
{
name: 'PersonLName'
},
{
name: 'PersonName',
convert: function(value, record) {
return record.data.PersonFName + ' ' +
record.data.PersonLName;
}
}
]
});
Store:
// changed to "Person" instead of "PersonStore"
Ext.define('MyApp.store.Person', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Person'
],
model: 'MyApp.model.Person',
proxy: {
type: 'ajax',
api: {
read: 'person.php',
create: 'person.php'
},
reader: 'array'
}
});
View:
{
xtype: 'combobox',
id: 'personcombo',
readOnly: false,
selectOnFocus: true,
forceSelection: true,
store: 'Person',
valueField: 'PersonID',
displayField: 'PersonName' // the converted field
}
Your combobox has 'Person' as the store, but I don't see you create a store called Person anywhere. Try store: Ext.create('MyApp.store.PersonStore', {autoLoad: true}).
You can also simplify your store:
Ext.define('MyApp.store.PersonStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Person'
],
model: 'MyApp.model.Person',
proxy: {
type: 'ajax',
api: {
read: 'person.php',
create: 'person.php'
},
reader: 'array'
}
});

How to use inner properties of a JSON response with Sencha Proxy

The JSONP proxy is largely working for me, but I need to set properties of a model based on some nested properties in the JSON response. I can't figure how to do this without extending the Reader class, but thought there might be an easier way that I'm just missing.
My Recipe model:
Ext.define('NC.model.Recipe', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'name', type: 'string' },
{ name: 'image', type: 'string' },
{ name: 'preparationText', type: 'string' },
{ name: 'ingredientsText', type: 'string' },
{ name: 'servings', type: 'string' }
]
}
});
My Store:
Ext.define('NC.store.Recipes', {
extend: 'Ext.data.Store',
config: {
model: 'NC.model.Recipe',
storeId: 'Recipes',
proxy: {
type: 'jsonp',
url: 'http://anExternalSite.com/api',
callbackKey: 'callback',
filterParam: 'text',
extraParams: {
type: 'Recipe'
},
reader: {
type: 'json',
idProperty: 'uuid',
}
}
}
});
The JSON format:
[
{
uuid: "/UUID(XXXX)/",
name: "Spicy Peanut Noodle Salad",
image: "http://someplace.com/noodle-salad.jpg",
properties: {
preparationText: "Make it all nice and stuff",
ingredientsText: "Heaps of fresh food",
servings: "serves 4",
}
},
{ ... },
{ ... }
]
I would like those 3 'properties' - preparationText, ingredientsText, and servings, to be placed in the model, but currently only id, name, and image are. What is the method to make this work? If it does involve extending the Reader class, some direction would be great.
Thanks.
You can change your code like this to access nested values
{ name: 'preparationText', type: 'string', mapping: 'properties.preparationText' },
This mapping path should start excluding the root element.

ExtJs4 Model with different poxy url's

I have defined a model which I want to use twice but with a different url int he proxy (in fact only the id differs) But how can I manage this?
Ext.define('TesterModel', {
extend: 'Ext.data.Model',
autoLoad: false,
fields: [
{ name: 'prename', type: 'string' },
{ name: 'lastname', type: 'string' },
{ name: 'dept', type: 'string' },
{ name: 'rackName', type: 'string' },
{ name: 'rackIP' , vtype:'IPAddress'}],
proxy: {
type: 'ajax',
url: 'php/getData_db.php?id=',
reader: {
type: 'json',
messageProperty: 'message',
root: 'data',
}
},
constructor: function() {
UrlParams=document.URL.split("?");
if(UrlParams.length > 1) {
SingleUrlParams=Ext.Object.fromQueryString(UrlParams[1]);
this.proxy.url = this.proxy.url + SingleUrlParams.right;
console.log(this.proxy.url);
}
return this;
}});
Ext.ModelMgr.getModel('TesterModel').load(0, { // load user with ID of "0"
success: function(tester) {
var rightPanel=Ext.getCmp('rightTester');
rightPanel.loadRecord(tester); // when tester is loaded successfully, load the data into the form
}
});
I thought that the constructor will be done before loading, but nope, it is done after. It's weired to me.
Any hints, please?
(the main URL it's like: .../index.html?left=xx&right=yy )
so I want to fill up a panel on the left with the one id, and a panel on the right window side eith th right id.
Thanks!
Try .getProxy().url = "what/ever.php"