I'm completely new to Extjs. I'm trying to get data using proxy like in this guide but I still don't understand it. The code is written like this.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'email']
});
//The Store contains the AjaxProxy as an inline configuration
var store = Ext.create('Ext.data.Store', {
model: 'User',
proxy: {
type: 'ajax',
url : 'users.json'
}
});
store.load();
My question is very basic. Is this code written in the same file, in my case, (root)/app/view/user.js or should I put it in different file? And how to do it if it is in separated file. Fyi, I got error when I put it in the same file.
In ExtJs have store proxy and also Ajax request you can use both.
Proxies are used by Ext.data.Store to handle the loading and saving of Ext.data.Model data. Usually developers will not need to create or interact with proxies directly.
Ajax singleton instance of an Ext.data.Connection. This class is used to communicate with your server side code.
I have created and Sencha Fiddle demo. Here I have create 2 local json file (user.json & user1.json).
I am fetching data using store proxy(from user.json) and Ext.ajax request(from user1.json).
Hope this will help you to solve your problem.
*Note this will work for both modern and classic.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['name', 'email', 'phone']
});
Ext.create('Ext.data.Store', {
storeId: 'userStore',
model: 'User',
proxy: {
type: 'ajax',
url: 'user.json',
reader: {
dataType: 'json',
rootProperty: 'data'
}
}
});
Ext.create('Ext.panel.Panel', {
width: '100%',
renderTo: Ext.getBody(),
padding: 15,
items: [{
xtype: 'button',
margin:5,
text: 'Get Data using Store Load',
handler: function () {
var gridStore = this.up().down('#grid1').getStore();
gridStore.load(function () {
Ext.Msg.alert('Success', 'You have get data from user.json using store.load() method..!');
});
}
}, {
xtype: 'grid',
itemId:'grid1',
title: 'User Data Table1',
store: Ext.data.StoreManager.lookup('userStore'),
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
height: 200,
width: '100%',
}, {
xtype: 'button',
margin:5,
text: 'Get Data using Ajax request',
handler: function () {
var me = this.up(),
gridStore = me.down('#grid2').getStore();
me.down('#grid2').mask('Pleas wait..');
Ext.Ajax.request({
url: 'user1.json',
method: 'GET',
success: function (response) {
me.down('#grid2').unmask();
var data = Ext.decode(response.responseText);
gridStore.loadData(data.data);
Ext.Msg.alert('Success', 'You have get data from user1.json using Ext.Ajax.request method..!');
},
failure: function (response) {
me.down('#grid2').unmask();
//put your failure login here.
}
});
}
}, {
xtype: 'grid',
itemId: 'grid2',
title: 'User Data table2',
store: Ext.create('Ext.data.Store', {
fields: ['name', 'email', 'phone']
}),
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
height: 200,
width: '100%',
}]
});
Please read the points below to understand this. This link on architecture would be helpful.
a. Since you are have created a Universal application, it means you are using Ext JS 6 or above. For this, the folder structure of CMD generated app is as follows:
app
model
store
view
classic
src
view
modern
src
view
b. The app folder is for classes shared by the classic and modern views. This will typically be model definitions in app/model, and shared controllers and view models in app/view folders.
c. Code in classic folder can reference classes in app folder, but can not reference code in modern folder. Similarly, code in modern folder can reference classes in app folder, but can not reference code in classic folder. (It means the model, store, viewmodel and viewcontroller classes in modern and classic apps can extend these classes from the app folder.)
d. Best practice is to declare store in a viewmodel but if the store config is complex, then define its class in the store folder.
e.To declare store in a viewmodel of classic app, example is given below. Similarly you will do for the modern app also.
//MyApp/classic/src/view/main/MainModel.js
stores: {
articles: {
model: 'MyApp.model.MyModel',// in classic/src/model folder
autoLoad: true,
proxy: {
type: 'ajax',//if it's cross-domain, use jsonp
url : 'users.json',
reader: {
type: 'json', //this is default
rootProperty: 'data'//the location in data feed from where you want to start reading the data
}
}
}
}
Now bind this store in the view. For example, in a grid:
{
xtype: 'grid',
bind: {
store: '{articles}'
}
//More code
}
f. If store is defined in a class (e.g.classic/src/store/Articles.js), then declare in a viewmodel like this. Binding will be same as above.
//MyApp/classic/src/view/main/MainModel.js
stores: {
articles: {
type: 'mystore' //this is alias of store class.
model: 'MyApp.model.MyModel', //in classic/src/model folder
}
}
Hope this solves your problem.
Related
While developping an application I run some code on application launch:
Ext.application({
extend: 'TestApp.Application',
name: 'TestApp',
requires: [
'TestApp.*'
],
// The name of the initial view to create.
launch: async function () {
const store_org = Ext.getStore('Organizations');
const store_event = Ext.getStore('Events');
//more stuff here
}
});
Both stores are well defined:
Ext.define('TestApp.store.Organization', {
extend: 'Ext.data.Store',
storeId: 'Organizations',
alias: 'store.organizations',
model: 'TestApp.model.Organization',
autoLoad: true,
pageSize: 0,
proxy: {
type: 'ajax',
url: TestApp.util.Config.getHost() + '/organization/get-organizations',
withCredentials: true,
reader: {
type: 'json',
rootProperty: '',
},
},
});
I do notice however that while launching the Ext.getStore() function always returns undefined for any store. Is there any way I can "delay" this to the point where the storemanager has fully loaded and these stores do no longer return undefined? (The stores themselves won't be filled with data...).
Just add this to the Ext.application class or to the TestApp.application (which is better)
stores:['TestApp.store.Organization'],
this is an array of all your stores,so if you need to add more just use a comma and write the class path name of the new file
Here is a working example Fiddle
I'm working with ExtJs 6.2.0 and Java Spring MVC for the REST API.
I'm trying to delete an object from one of my store but I'm having a problem : instead of using my id named idCamp, extjs is using the field named id that contains an extjs generated id (for example: extModel47-1).
I'm working on the delete part but I didn't try to update a camp nor fetch one, but I think the configuration is the same for these three operations that need the id.
Here is my store:
Ext.define('XXXXXX.store.Camps', {
extend: 'Ext.data.Store',
alias: 'store.camps',
model: 'XXXXXX.model.Camp',
fields: [
'idCamp', // More irrelevant fields
],
autoLoad : true,
autoSync: true,
storeId: 'storeCamp',
proxy: {
type: 'rest',
idParam: 'idCamp',
url: // irrelevant,
reader: {
type: 'json',
rootProperty: 'data'
},
writer: {
type: 'json'
}
}
});
Here is my model:
Ext.define('XXXXXX.model.Camp', {
extend: 'Ext.data.Model',
idProperty: 'idCamp',
fields: [
{ name: 'idCamp', type: 'int' },
// More irrelevant fields
]
});
I also tried to put an idProperty inside the writer/reader inside the proxy but it didn't do anything.
Forgive my poor usage of the English language since I'm a French people.
Best regards,
Morony
The issue is using a combination of fields/model in your store definition. They are in competition with each other. Remove the fields definition.
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.
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
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/