Binding a Simple Viewmodel with Single Record - javascript

I created this fiddle showing what I want to do.
Basically, I configured a Store that loads only a single record (it reality it will be the currently signed in user). However, I can't seem to bind anything to that store properly. How can I get that {u.name} to output properly?
Here is the code:
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id', 'name']
});
Ext.application({
name : 'Fiddle',
launch : function() {
new Ext.Component({
renderTo: Ext.getBody(),
viewModel: {
stores: {
u: {
proxy: {
type: 'ajax',
url: 'user.json'
},
model: 'User',
autoLoad: true
}
}
},
bind: 'Test name: {u.name}'
});
}
});

Try bind: 'Test name: {u.data.items.0.name}'
UPD:
As an explanation to this - u is an object with its properties, so trying to bind to u.name will actually bind to the name property of the store. Wile the store has no name property it will always be null. Store's received data is placed in data property. Items property contains a raw array of received data and so on.

In your fiddle you're using a store while it looks like you need just a single record.
Using links instead of stores should work better, like:
links: {
u: {
type: 'User',
id: 1
}
}
Working example based on your code: https://fiddle.sencha.com/#fiddle/uuh

Related

Ext JS dynamic store insert Cannot read property 'isModel' of undefined

I dynamically create my store from a model relation and attach this store to a grid.
var map = record.getCommunity().mappings();
map.load({
url: '/myUrl/mappings',
scope: this,
callback: function(records, operation, success) {
map.group('type');
//ExtJS bug https://www.sencha.com/forum/showthread.php?265674
me.getOutgoingGrid().destroy();
childGrid = Ext.create('hds.view.outgoingGrid', {
store: map
});
me.getGridHolder().add(childGrid);
me.getOutgoingGrid().getSelectionModel().select(0, false) ;
}
});
When I want to create a new model instance and insert it into this dynamic store I get the following error:
Cannot read property 'isModel' of undefined
Here is the code that triggers the error:
var newMap = Ext.create('hds.model.MappingModel', {
indetifier : "something",
});
me.getOutgoingGrid().store.insert(0, newMap);
I cannot found the reason of this problem....Any ideas?
It is hard to know what is breaking your code but here are a couple of things:
1 - You need to define the model identifier in the class prototype not in the instance.
2 - You misspelled identifier
So your model should look like:
Ext.define('hds.model.MappingModel', {
identifier : "something",
});
var newMap = new hds.model.MappingModel({
//...your config here
});
The error that you are seeing Cannot read property 'isModel' of undefined is thrown when the store tries to check if model is an instance of Ext.data.Model but the model being passed is undefined.
This can happen for several reasons but usually it's because you are trying to create a model before the prototype has been defined or because there is a typo on your code.
Please, try creating a a fiddle (https://fiddle.sencha.com) reproducing this error or it will be very hard to help you.
Regards,
If there was an fiddle, It would be more helpful. As I understand from your question, you have some data and you can't set the data to store or model correctly. If you had defined your model or store before set to grid, there would not be a problem. I added a fiddle how model proxy works with store and etc. Hope it helps. If the fiddle does not explain your problem, please change the fiddle codes. So, we can understand what your problem exactly. Here is the fiddle: https://fiddle.sencha.com/#fiddle/tvq
Ext.define('model.Users', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Name', type: 'string'},
{ name: 'City', type: 'string'},
{ name: 'Country', type: 'string'},
],
//idProperty: 'Name',
proxy: {
type: 'ajax',
rootProperty: 'records',
rootUrl: 'users', // used when updating proxy url
url: 'users',
reader: {
type: 'json',
rootProperty: 'records'
}
}
}); //model
var modelExt = Ext.create('model.Users', { Name: 'Ernst Handel'});
var storeExt = Ext.create('Ext.data.Store', {
requires: 'model.Users',
model: 'model.Users'
});
modelExt.load({
scope: this,
success: function(record) {
var colObjects = [];
Ext.each(Object.keys(record.data), function(key) {
colObjects.push({
text: key,
dataIndex: key
});
});
storeExt.loadData([record]);
//console.log(record, storeExt);
var grid = Ext.create('Ext.grid.Panel', {
store: storeExt,
columns: colObjects,
renderTo: Ext.getBody()
});
},
failure: function (err) {
}
});
Create model like this and then use.
var newMap = Ext.create('Ext.data.model', {
identifier : "something"
});
Add a new file in Model folder named like MappingModel.js and define model like this.
Ext.define('hds.model.MappingModel', {
extend: 'Ext.data.Model',
fields: [
'something'
]
});
Add this in app.js and then use MappingModel in your dynamic store.

Dynamically define and load views with different proxy store in Sencha Touch 2

I am creating a mobile application with Sencha Touch 2 that would load its views dinamically depending on a Json response from the server.
It means that before the load of the view I have to compose the view with some generic elements. For example, if I receive a Json string from the server corresponding to a List view I would have to dinamically fill the list items (name, url, descriprion) with a store and a proxy.
This works, but then I would like to select some item on that list and load another list, but this time I want to change the proxy. My new proxy is the url field from the selected item. I get the url field from the selected item and change the proxy, but this introduces a problem:
I am using an Ext.navigation.View, and I want to maintain navigation history. In the above case, if I go back in the navigation history the items on the first list change to the items on the last list.
I am searching for some kind of workflow to achieve dynamic load of the views depending on independent data for each one, and always maintaining the MVC-Store pattern and the navigation history.
This is my model for the list item:
Ext.define('ExampleApp.model.ListItem', {
extend: 'Ext.data.Model',
config: {
fields: ['name', 'url', 'descriprion']
}
}
This is the store for the List:
Ext.define('ExampleApp.store.ListItems', {
extend: 'Ext.data.Store',
config: {
autoLoad: false,
model: 'ExampleApp.model.ListItem',
proxy: {
type: 'jsonp'
url: 'http://mydomain.com/myjsonresponse',
reader: {
type: 'json',
useSimpleAccessors: true
}
}
}
})
This is my view:
Ext.define('ExampleApp.view.MyList', {
extend: 'Ext.List',
xtype: 'mylist',
requires: ['ExampleApp.store.ListItems'],
config: {
title: 'My List',
itemTpl: '{name} - {description}',
store: 'ListItems'
}
})
This is the function called on the itemtap event of my list:
listItemTapped: function (view, index, target, record, event) {
var listItems = Ext.getStore('ListItems');
listItems.getProxy().setUrl(record.get('url'));
listItems.load();
this.getMain().push({
xtype: mylist
});
}
What you can try is creating separate store for each list instead of reusing existing one.
listItemTapped: function (view, index, target, record, event) {
var listItems = Ext.create('ExampleApp.store.ListItems', {newUrl : record.get('url')});
listItems.load();
this.getMain().push({
xtype: mylist,
store: listItems
});
}
and add initialize function to use newUrl:
Ext.define('ExampleApp.store.ListItems', {
extend: 'Ext.data.Store',
config: {
autoLoad: false,
newUrl : null,
model: 'ExampleApp.model.ListItem'
},
initialize : function() {
this.setProxy({
type: 'jsonp'
url: this.config.newUrl,
reader: {
type: 'json',
useSimpleAccessors: true
}
});
}
})
You may want to destroy these stores once their view is popped.
#ThinkFloyd, agree that we need to destroy the store when we leave the view, as it will create a problem later when application has many views and has larger stores with lots of data. I recently face the same issue and this helps me a lot...thanks

Save nested form data back to server in ExtJS

I have a Model that contains an association to another Model. I am able to display the nested data into a form by using the mapping attribute on the field. Example:
Ext.define('Example.model.Request', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
type: Ext.data.Types.NUMBER,
useNull: false
}
{
name: 'plan_surveyor',
mapping: 'plan.surveyor',
type: Ext.data.Types.STRING
}
],
associations: [
{type: 'hasOne', associationKey: 'plan', getterName:'getPlan', model: 'Specs.model.Plan'}
],
proxy: {
type: 'direct',
api: {
read: requestController.load,
update: requestController.update,
},
reader: {
type: 'json',
root: 'records'
},
writer: {
type: 'json',
writeAllFields: true,
nameProperty: 'mapping'
}
}
});
Using this method, I can display the plan.surveyor value in the form by reference plan_surveyor. I call Form.loadRecord(model) to pull the data from the model into the form.
However, now that I'm trying to send the data back to the server, I get the error:
Error performing action. Please report the following: "Unrecognized field "plan.surveyor"
I am attempting to save to the server by first calling Form.updateRecord(model), then model.save(). Is there a way to have the Writer understand that 'plan.surveyor' is not a property name but instead to properly handle nesting?
Am I doing this the right way to start with, or should I just be handling the setting of the form data and loading back into the model in a more manual fashion? It seems that nested data is not all that well supported in general - any recommendations?
Ext.define('Example.model.Request', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
type: Ext.data.Types.NUMBER,
useNull: false
}
{
name: 'plan_surveyor',
mapping: 'plan.surveyor',//change to 'plan_surveyor'
type: Ext.data.Types.STRING
}
],
change that show in comment ,because data index is given in above format because ur give ur format thata time that is not dataindex it's a column or extjs preparatory ,so please change that may it's work well
it's not work u will send hole code

Map ExtJS Proxy AJAX response to model

UPDATE:
here is my reader/store - not sure what to add to the reader to make this work
Ext.define('YT.store.Videos', {
extend: 'Ext.data.Store',
model: 'YT.model.Video',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'https://gdata.youtube.com/feeds/api/videos',
reader: {
type: 'json',
root: 'feed',
record: 'entry',
successProperty: 'success'
},
listeners: {
exception: function(store, response, app){
console.log('exception...');
console.log(response);
}
}
}
});
Here is my model:
Ext.define('YT.model.Video', {
extend: 'Ext.data.Model',
autoLoad: true,
fields: [
'title',
'published',
'content'
]
});
Here is a sample response:
{
version: '1.0',
encoding: 'UTF-8',
feed: {
junk: 'blahblahblahblah',
entry: [
title: {
$t: 'title'
},
content: {
encoding: 'flash/application',
src: 'http://youtube.com/watch?q=someCatVideo'
},
published: {
$t: '12-28-2012'
}
]
}
}
I'm not sure how to reconcile the two.
I've tried...
Ext.define('YT.model.Video', {
extend: 'Ext.data.Model',
autoLoad: true,
fields: [
{name: 'title', mapping: 'title.$t'},
{name: 'published', mapping: 'published.$t'},
{name: 'content', mapping: 'content.src'}
]
});
Bonus:
Definitely looking for tips on how to debug the implementation of these techniques, I'm rather new to JavaScript MVC.
You are on the right track with mapping, but you also need to define a reader where you specify where your records are in the JSON you get back - see official docs for good examples.
Incidentally, who thought $t was a good idea for a map key?
EDIT:
After your edits here is your working code:
http://jsfiddle.net/dbrin/mSJg3/
As far as debugging: the key for your issue was to clearly see the payload from the service (I used FireBug to inspect JSON object returned). Then mapping your Model class to fit the JSON object through mapping attribute and finally adjust JSON reader to let it know how to navigate your JSON payload (see my code example).
Once your exception listeners are not firing anymore (see code example for those again) that means you got your data into the store. To actually see the data I used Illuminations firebug plugin to inspect the data store. I saw only one record. What the heck? I observed id Property being set to some funky URL. This was happening by default as i did not specify an id attribute on the model. I resorted to spacifying idProperty to undefined to get around this funky behavior (see model code).
I used jsfiddle to quickly iterate through changes and running to see errors in the reader. Once I had no more errors I had jsfiddle show me the app I just build in such a way that I could use Illuminations plugin by using the show/light url: http://jsfiddle.net/dbrin/mSJg3/show/light/

ExtJS4 Changing data store parameters

If I have a data store on a grid like so:
store = Ext.create('Ext.data.Store', {
fields: [{
name: 'id'
}, {
name: 'filename'
}
// other fields here ...
],
proxy: {
type: 'ajax',
url: 'http://myniftyurl.com/blah',
simpleSortMode: true,
reader: {
type: 'json',
totalProperty: 'total',
root: 'result'
},
extraParams: {
'limit': Ext.get('itemsPerPage').getValue(),
'to': Ext.get('to_date').getValue()
// other params
}
},
model: 'Page',
remoteFilter: true,
remoteSort: true
});
The 'limit' and 'to' value will change based on user input, therein lies the problem. The data store keeps using the original parameters instead of the new inputs. How can I fix this?
Thanks in advance!
I normally load my grids manually by executing the store.load() in the controller.
That way prior to it I can change the store's params like so:
//getForm() retrieves the Ext.basic.Form (from Ext.panel.Form)
var params = this.getForm().getValues();
//Write over
grid.getStore().getProxy().extraParams = params;
//load
grid.getStore().load();
I'm using buffered grids which required a decent amount of rework to get completely working in 4.0.7. But that should work for you.
Another options is to use a beforeload listener but I'm not sure if changing the extraParams by then will do anything. You may be able to modified the Ext.data.Operation object that gets passed to the event handler?
Let me know how that works out for you.
Good luck!

Categories