I rewrite my working Fiddle from ajax proxy type to memory. I'm trying to load memory store data manually:
// app/model/Employees.js file
Ext.define('Fiddle.model.Employees', {
extend: 'Ext.data.Model',
entityName: 'Employees',
fields: [
{
name: 'profile_pic'
},
{
type: 'int',
name: 'age'
},
{
type: 'string',
name: 'last',
mapping: 'name.last'
},
{
type: 'string',
name: 'first',
mapping: 'name.first'
},
{
type: 'string',
name: 'email'
}
],
proxy: {
type: 'memory',
reader: {
type: 'json',
rootProperty: 'items',
totalProperty: 'total',
successProperty: ''
}
}
});
// app/store/Employees.js file
Ext.define('Fiddle.store.Employees', {
extend: 'Ext.data.Store',
pageSize: 30, // items per page
alias: 'store.employees',
model: 'Fiddle.model.Employees',
});
//app.js fule - launch() function
var store = Ext.create('Fiddle.store.Employees');
console.log(store);
Ext.Ajax.request({
url: 'mates.json',
success: function(resp) {
var result = resp.responseText;
console.log(result);
// store.loadRawData(result);
store.loadData(result);
console.log(store);
console.log(store.getAt(0));
},
});
As result I have 3386 records in store, every symbol in my json file. And what I see in console as first record:
What I'm doing wrong?
And where I need to put proxy lines - in model or in store?
responseText is a string, which contains the serialized JSON data. You have to deserialize it into an object before you can use loadRawData to load the object through the model converters into the store:
var result = Ext.decode(resp.responseText);
store.loadRawData(result);
loadData and loadRawData differ in that loadData does not call the converters on the model. loadRawData is equivalent to what the ajax proxy does, loadData is not.
Did it in this way:
//in Grid panel js file
listeners: {
afterrender: function(grid, evt) {
var myStore = grid.getStore();
Ext.Ajax.request({
url: 'mates.json',
success: function(resp) {
var result = Ext.decode(resp.responseText);
myStore.getProxy().data = result;
myStore.load();
},
});
}
}
In store autoLoad: true must be disabled. This way of loading instead of store.loadRawData(result); shows the correct number of records in the pagingtoolbar.
Related
So I have upgraded from extjs4 to extjs6 and this store always have this error:
No type specified for writer.create
This code has two uses:
For getting the data for the initial page
For getting the data for whenever a button is clicked.
Whenever I comment out the proxy.writer code portion, it will produce the data for the initial page.
But whenever I won't comment it out, it will not get the data for the initial page.
And it will also return this error whenever I clicked a button:
Uncaught TypeError: items.slice is not a function
So my question is, is the writer portion have wrong syntax or something since it is updated to extjs6?
P.S. I tried to change the
this.callOverridden to this.callParent since it states that the this.callOverridden is already deprecated, still has the same error.
Ext.define('Stm.store.stmpdate', {
extend: 'Extends.data.Store',
requires: [
'Cstm.Setting',
'Stm.model.stmpdate'
],
model: 'Stm.model.stmpdate',
pageSize: Stm.Const.controller.dataCountLimit,
remoteSort: true,
proxy: {
type: 'ajax',
url: Cstm.Setting.getEntryUrl() + '/stm/stm-update/stm-update',
reader: {
type: 'json',
rootProperty: 'data'
},
writer: Ext.data.writer.Json.override({
getRecordData: function() {
var data = this.callOverridden(arguments);
var record = arguments[0];
if ( record.associations.length > 0 ) {
Ext.Array.each(record.associations.keys, function(key) {
data[key] = [];
var assocStore = record[key]();
Ext.Array.each(assocStore.data.items, function(assocItem) {
data[key].push(assocItem.data);
});
});
}
return data;
}
}),
api: {
create: Cstm.Setting.getEntryUrl() + '/stm/stm-update/application',
update: Cstm.Setting.getEntryUrl() + '/stm/stm-update/approval'
},
actionMethods: {
create: 'POST',
read: 'POST',
update: 'POST',
destroy: 'POST'
}
},
sorters: [
{property: 'aplDatetime', direction: 'DESC'},
{property: 'siteDomain', direction: 'ASC'},
{property: 'pageName', direction: 'ASC'}
]
});
Model:
Ext.define('Stm.model.stmpdate', {
extend: 'Ext.data.Model',
fields: [
{name: 'siteId', type: 'integer'},
{name: 'siteName', type: 'string'},
{name: 'siteUrl', type: 'string'},
{name: 'tmpId', type: 'integer', defaultValue: 1},
{name: 'updType', type: 'string'}
],
hasMany: [{
model: 'Stm.model.ServerInfo',
name: 'servers',
associationKey: 'servers',
reference: 'tmpId'
}]
});
Yes, you are using override in a way that may have worked in ExtJS 4 but is AFAIK unsupported across all versions of ExtJS.
What you want to do is define your custom writer as a new class:
Ext.define('MyApp.app.data.MyCustomJsonWriter', {
extend: 'Ext.data.writer.Json',
alias: 'writer.mycustomjson',
getRecordData: function() {
var data = this.callParent(arguments);
var record = arguments[0];
if ( record.associations.length > 0 ) {
Ext.Array.each(record.associations.keys, function(key) {
data[key] = [];
var assocStore = record[key]();
Ext.Array.each(assocStore.data.items, function(assocItem) {
data[key].push(assocItem.data);
});
});
}
return data;
}
});
require that class from your store:
requires: [
'MyApp.app.data.MyCustomJsonWriter'
]
and then instantiate it by alias:
writer: {
type: 'mycustomjson'
}
Model
Ext.define('MyDesktop.model.mail.MailFoldersModel', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.field.String'
],
fields: [
{
type: 'string',
name: 'id'
},
{
type: 'string',
name: 'idParent'
},
{
type: 'string',
name: 'text'
}
]
});
My TreeStore
Ext.define('MyDesktop.store.mail.MailFoldersStore', {
extend: 'Ext.data.TreeStore',
requires: [
'MyDesktop.model.mail.MailFoldersModel'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'MailFoldersStore',
model: 'MyDesktop.model.mail.MailFoldersModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'http://url/mail/folders',
reader: {
type: 'json',
rootProperty: 'items',
successProperty: 'success'
}
},
root: {
text: 'root',
iconCls: 'mail-folders-owner'
}
}, cfg)]);
}
});
Store is autoloaded, all works correctly, store contains 11 records.
var MailFoldersStore = Ext.create('MyDesktop.store.mail.MailFoldersStore', {
storeId: 'MailFoldersStore'
});
If I set autoLoad to false and trying to load by manually - store is empty, 0 records.
var MailFoldersStore = Ext.create('MyDesktop.store.mail.MailFoldersStore', {
storeId: 'MailFoldersStore'
});
MailFoldersStore.load({
callback : function(records, operation, success) {
console.log(records);
}
});
What can be a reason for this behaviour?
I also has same problem. I am using Extjs 5.1. After googling I found one complex solution which needs us to modify the framework.
See the below link if it can help you.
http://www.sencha.com/forum/showthread.php?154823-listeners-quot-exception-quot-in-proxy.ajax-on-TreeStore-do-not-work
I'm trying to create a store and inside access the data from another store to construct the proxy url.
Something like this:
Ext.define('MyApp.store.Post',{
extend:'Ext.data.Store',
config: {
model: 'MyApp.model.Post',
proxy: {
type: 'ajax',
url: 'http://mywebsite.com/get?userid=' + Ext.getStore('UserData').getAt(0).data.userid,
reader: {
type: 'json'
}
}
}
});
So, I'm basically trying to get the userid from another store to be able to construct the correct url.
This doesn't work, I get:
Uncaught TypeError: Object #<Object> has no method 'getStore'
What is the correct way to do this?
EDIT: Okay I put in a dummy URL and trying to change it with a listener, this is my store now:
Ext.define('MyApp.store.Post',{ extend:'Ext.data.Store',
config: {
fields: [
'title', 'link', 'author', 'contentSnippet', 'content'
],
proxy: {
type: 'jsonp',
url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
reader: {
type: 'json',
rootProperty: 'responseData.feed.entries'
}
},
listeners: [
{
beforeload: function(){
console.log("store loaded"); //I DON'T SEE THIS IN CONSOLE
return true;
}
}
]
},
});
Basically you did nothing wrong, but the reason is sencha touch uses asynchronous loading and it seems that Ext.getStore() is not instantiated at the time your store is defined.
Let's try this method instead:
First, add a listener for beforeload event inside your store config:
Ext.define('MyApp.store.Post',{
extend:'Ext.data.Store',
config: {
model: 'MyApp.model.Post',
proxy: {
type: 'ajax',
//url: you don't even need to set url config here, simply ignore it
reader: {
type: 'json'
}
}
},
listeners: [
{
fn: 'setUrl',
event: 'beforeload'
}
]
});
then declare a function like this, in the same file:
setUrl: function(){
this.getProxy().setUrl(Ext.getStore('UserData').getAt(0).data.userid);
return true;
}
This way, it's ensured to set the url for your store's proxy right before it's loaded. And basically at the time, all core methods are instantiated.
Update: please try this with your Post store:
Ext.define('MyApp.store.Post',{
extend:'Ext.data.Store',
config: {
//autoLoad: true,
fields: ['title', 'link', 'author', 'contentSnippet', 'content'],
proxy: {
type: 'jsonp',
url: 'dummy url',
reader: {
type: 'json',
rootProperty: 'responseData.feed.entries'
}
},
},
initialize: function(){
console.log("loaded!");
this.getProxy().setUrl('https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog');
//return true;
}
});
After reading the source code of the pull-to-refresh plugin, I see that Sencha Touch use an Ext.data.Operation instead of Ext.data.Store.load() function. So you will have to put it into the initialize method instead.
Use Ext.data.StoreManager.lookup('UserData') to get the store instance.
But in your case, I would use this somewhere, where you work with the userid:
var postsStoreInstance = ...;
postsStoreInstancegetProxy()._extraParams.userid = userid;
It adds a query paremetry to the store's proxy url
The way you do it is the correct way. What is the code of your store definition?
Make sure your store has storeId: 'UserData'.
See this working example:
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'id'}
]
});
Ext.create( 'Ext.data.Store', {
model: 'User',
storeId: 'UserData'
});
Ext.define('MyApp.store.Post',{
extend:'Ext.data.Store',
config: {
model: 'MyApp.model.Post',
proxy: {
type: 'ajax',
url: 'http://mywebsite.com/get?userid=' + Ext.getStore('UserData'),
reader: {
type: 'json'
}
}
}
});
I want to get data from mongo data base and add it to an extjs text area.
Everything is ready, my mongo data base returns a list of user email addresses that I want to add to the extjs text area.
I use this code:
var index = Ext.StoreMgr.lookup("writeup.store.Employee").findExact('name',name);
var rec = Ext.StoreMgr.lookup("writeup.store.Employee").getAt(index);
alert(rec.data.name);
But I get this error:
TypeError: Ext.StoreMgr.lookup(...) is undefined
And this is my store
Ext.define('writeup.store.Employee', {
extend: 'Ext.data.Store',
model: 'writeup.model.Employee',
autoLoad: true,
proxy: {
type: 'ajax',
actionMethods: {
read : 'POST'
},
api: {
read : 'user/view.action'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: false,
root: 'employee'
},
listeners: {
exception: function(proxy, response, operation){
Ext.MessageBox.show({
title: 'REMOTE EXCEPTION',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
try this
Load this code into your controller
var store_name = Ext.create('Ext.data.Store', {
model: 'model name'
});
store_name.load();
store_name.each(function(record){
for(var i=0;i<record.data.yourlocalstorageid.length;i++){
var index = record.data.yourlocalstorageid[i].name;
}
}
So I have a parent and child store, illustrated here:
Parent Model
Ext.define('APP.model.Client', {
extend: 'Ext.data.Model',
requires: [
'APP.model.Website', 'Ext.data.association.HasMany', 'Ext.data.association.BelongsTo'],
fields: [{
name: 'id',
type: 'string'
}, {
name: 'name',
type: 'string'
}, {
name: 'slug',
type: 'string'
}, {
name: 'active',
type: 'boolean'
}, {
name: 'current',
type: 'boolean'
}],
hasMany: {
model: 'APP.model.Website',
name: 'websites'
}
});
Child Model
Ext.define('APP.model.Website', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'string'
}, {
name: 'client_id',
type: 'string'
}, {
name: 'sub_domain',
type: 'string'
}, {
name: 'active',
type: 'boolean'
}],
belongsTo: 'APP.model.Client'
});
Using an AJAX call via the server, I am loading the Clients store, and that is loading fine. But the Websites store isn't populated, and when I breakpoint on the Clients store on.load function, to see what it's populated with, the Client store is only populated with the client data, but in the raw property for that store, I can see all the websites data. So it's being returned correctly, but my extjs isn't correct. Here are the stores:
Client Store
Ext.define('APP.store.Clients', {
extend: 'Ext.data.Store',
autoLoad: false,
model: 'APP.model.Client',
proxy: {
type: 'ajax',
url: '/client/list',
reader: {
type: 'json',
root: 'items'
}
},
sorters: [{
property: 'name',
direction: 'ASC'
}]
});
Websites Store
Ext.define('APP.store.Websites', {
extend: 'Ext.data.Store',
requires: ['Ext.ux.Msg'],
autoLoad: false,
model: 'APP.model.Website',
proxy: {
type: 'ajax',
url: '/client/list',
reader: {
type: 'json',
root: 'items'
},
writer: {
type: 'json'
}
},
sorters: [{
property: 'sub_domain',
direction: 'ASC'
}]
});
My final result is...I would like to populate both stores so I can click on an element, and when it loads something from the parent store, I can access the child store(s) (there will be more when I figure out this problem) to populate a couple grid(s) in tabs.
What am I missing as far as my setup? I just downloaded extjs4 a couple days ago, so I am on 4.1.
Put your proxies in your models, unless you have a good reason not to [1]
Make sure you require the related model(s), either in the same file, or earlier in the application
Use foreignKey if you want to load the related data at will (i.e. with a later network request).
Use associationKey if the related data is loaded in the same (nested) response
Or just use both
Always name your relationships (otherwise the name will be weird if using namespaces).
Always use the fully qualified model name for the model property in your relationships
Working code:
model/Contact.js:
Ext.define('Assoc.model.Contact', {
extend:'Ext.data.Model',
requires:[
'Assoc.model.PhoneNumber'
],
fields:[
'name' /* automatically has an 'id' field */
],
hasMany:[
{
model:'Assoc.model.PhoneNumber', /*use the fully-qualified name here*/
name:'phoneNumbers',
foreignKey:'contact_id',
associationKey:'phoneNumbers'
}
],
proxy:{
type:'ajax',
url:'assoc/data/contacts.json',
reader:{
type:'json',
root:'data'
}
}
});
model/PhoneNumber.js:
Ext.define('Assoc.model.PhoneNumber', {
extend:'Ext.data.Model',
fields:[
'number',
'contact_id'
],
proxy:{
type:'ajax',
url:'assoc/data/phone-numbers.json',
reader:{
type:'json',
root:'data'
}
}
});
data/contacts.json:
{
"data":[
{
"id":1,
"name":"neil",
"phoneNumbers":[
{
"id":999,
"contact_id":1,
"number":"9005551234"
}
]
}
]
}
data/phone-numbers.json
{
"data":[
{
"id":7,
"contact_id":1,
"number":"6045551212"
},
{
"id":88,
"contact_id":1,
"number":"8009996541"
},
]
}
app.js:
Ext.Loader.setConfig({
enabled:true
});
Ext.application({
requires:[
'Assoc.model.Contact'
],
name:'Assoc',
appFolder:'Assoc',
launch:function(){
/* load child models that are in the response (uses associationKey): */
Assoc.model.Contact.load(1, {
success: function(record){
console.log(record.phoneNumbers());
}
});
/* load child models at will (uses foreignKey). this overwrites child model that are in the first load response */
Assoc.model.Contact.load(1, {
success: function(record){
record.phoneNumbers().load({
callback:function(){
console.log(arguments);
}
});
}
});
}
});
[1] A store will use its model's proxy. You can always override the store's proxy if need be. You won't be able to use Model.load() if the model has no proxy.
Your assumption is wrong. You expect that the WebSite store loads itself but that is not how it works. What you can do is the following (this is untested but is how I do it in all my projects):
In your clients grid add a listener for the itemclick event to call the following method (showWebSites). It will receive the selected client record containing the selected APP.model.Client instance. Then, and given that each client has a set of WebSites, the method will load the APP.store.Websites store and the client´s websites will be displayed in your view.
showWebSites: function (sender, selectedClient) {
Ext.StoreManager.lookup('APP.store.Websites')
.loadData(selectedClient.data.WebSites);
}
This is the way. I hope you find it useful.