ExtJS 4.1 - Changing value of JsonStore - extjs

I use ExtJS 4.1. Here's my model and store:
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: ['status', 'data', 'data1', 'data2']
});
var store1 = Ext.create('Ext.data.JsonStore', {
model: 'MyModel',
proxy: {
type: 'ajax',
url : 'actionJsonServlet'
},
autoLoad: true
});
After loading the store by Ajax, I want to change value of first "status" (just for first row) of the JsonStore.
I tried lines below but it doesn't work (record is undefined at line 2):
var record = store1.getAt(0);
record.set("status", "Waiting");
I have this error:
Cannot call method 'set' of undefined

Most likely your issue is due to asynchronous nature of store load. Depending on how your code is written you maybe attempting to do store operations too early, before the store is loaded even though you have autoLoad turned on.
The best approach is to set up a load event listener on the store and perform your operation then.
Her is an example:
Ext.define('MyApp.store.Drafters', {
extend:'Ext.data.Store',
model:'MyApp.model.User',
autoLoad:true,
proxy:{
type:'ajax',
url:'user/drafters.json',
reader:{
type:'json',
root:'data'
}
},
listeners:{
load:function (store, recs) {
store.insert(0, {uid:'', name:''}); //adding empty record to enable deselection of assignment
}
}
});

Related

How to access other Store records from Model's convert method in ExtJS6?

I am trying to have a calculated field inside a Model that looks something like value (maxValue), where maxValue is the maximum value among all other records currently loaded (think current page of a Grid).
Model:
Ext.define('MyApp.model.Example', {
extend: 'Ext.data.Model',
fields: [
{name: 'id'},
{name: 'value'},
{name: 'calculated_value', convert: function(value, record){
//how to access all the records here, not just the current one?
}}
]
});
A model is not aware of records, it just represents a single record, and the convert method is intended to allow you to convert the value, or combine other fields into a single value (note unless you define "depends" to reference other fields in this instance the convert is only called when the data is loaded and not if the fields it depends on change).
When you create a grid, the grid uses a store, the store contains a collection of records, and this would be the place to do this.
Within the config for your store you could add a listener for 'datachanged' which will fire whenever records are added or removed from the store, from here you could work through all the records in the store, work out a max value, and update records with it.
Ext.create('Ext.data.Store', {
model: 'Example',
proxy: {
type: 'ajax',
url : 'example.json',
reader: {
type: 'json'
}
},
listeners:{
datachanged:function(store){
var maxValue=store.max('value');
store.beginUpdate();
store.each(function(record){
record.set('calculated_value',maxValue);
});
store.endUpdate();
}
}
});
If you are loading the store from a server, then you will be implementing a reader, this would possibly be an even better place to do this.
Ext.create('Ext.data.Store', {
model: 'Example',
proxy: {
type: 'ajax',
url : 'example.json',
reader: {
type: 'json',
transform: {
fn: function(data) {
var maxValue=0;
Ext.each(data.items,function(item){
if(item.value>maxValue) maxValue=item.value;
});
Ext.each(data.items,function(item){
item.calculated_value=maxValue;
});
return data;
},
scope: this
}
}
},
});
Its also worth clarifying if you really need to duplicate this value, I presume you then want to reference somehow within the grid, perhaps in a renderer, instead you could just set the value once on the store:
Ext.create('Ext.data.Store', {
model: 'Example',
proxy: {
type: 'ajax',
url : 'example.json',
reader: {
type: 'json'
}
},
listeners:{
datachanged:function(store){
store.maxValue=store.max('value');
}
}
});
Then within your grid column config, add/update a renderer (in this example I display value as a percentage of maxValue):
{
dataIndex:'value',
renderer:function(value, metaData, record, rowIndex, colIndex, store, view){
return Math.round((100/store.maxValue)*value)+'%';
}
}

How to restrict fire call when store will create

My store getting created in render function that one call get fired, but my requirement call should fired conditionally but store instance should create always.
For this requirement I am using following code for create store in render function,
Ext.create('mypage.store.customTreeGridStore', {
storeId: 'myStore',
proxy: {
type: 'rest',
startParam: undefined,
filterParam: undefined,
sortParam: undefined,
paramsAsJson: true,
limitParam: 'pageSize',
pageParam: 'pageNo',
restService: 'rest',
restOperation: 'getOperation',
url: me.urlparams,
autoLoad: true,
actionMethods: {
read: 'POST'
}
}
});
and I have added listener in store
beforeload: function(store, operation, eOpts) {
return booleanFlag;
}
When page is loading I could get beforeLoad boolean flag false and while page refreshing call is not getting fired but Store instance created successfully,
but I have text box where I am searching grid records. When I am searching any text in textbox I could not getting any record in grid.
But once booleanFlag is true I can search result in grid successfully . So what is the best way to resolve this issue?
Your store has autoLoad set to true, and to force the store to not load automatically all the time, you use the beforeload event to stop the autoLoad. Is this assessment correct?
How about, instead of
Ext.create('mypage.store.customTreeGridStore', {
proxy:{
autoLoad: true,
},
listeners:{
beforeload: function(store, operation, eOpts) {
return booleanFlag;
}
}
})
removing autoLoad and loading the store after creation only if required?
var store = Ext.create('mypage.store.customTreeGridStore', {
proxy:{
autoLoad: false,
}
});
if(booleanFlag) store.load();

how do we know which event fired load event in extjs 4.1 store

I am using extjs 4.1 store. Which looks like this:
Ext.define('myStore', {
extend: 'Ext.data.Store',
requires: ['myModel'],
autoLoad: false,
proxy: {
type: 'ajax',
url: '/aaa/bbb',
timeout: '90000',
reader: {
type: 'json',
root: 'data'
}
},
listeners: {
'beforeload': function (store, options) {
},
'load': function (store, options) {
}
},
sorters: [{
property: 'SortOrder',
direction: 'ASC'
}]
});
initially I am loading data through proxy. Later based on user interaction, I will extract the data from the store usign store.proxy.reader.rawData and store it in some variable.
Then at later stage, I will load into the store from the variable using loadRawData().
When loadRawData() is called, it also fires the load event.
What I want: I want to diffrentiate between load event fired due to proxy loading the data for the first time vs load event fired due to loadRawData().
Upgrading to ExtJS version 5.1 allows you access to store.loadCount which will let you to check whether this is the first load or a subsequent load. http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/#!/api/Ext.data.Store-property-loadCount
If you don't want to upgrade, you could manually implement this feature (e.g. increment a custom variable on your store in the 'load' listener) and check it to see which behaviour you want to perform.

Store.load() does not execute after setting a new model

I want to reconfigure a GridPanel using myGridPanel.reconfigure(store,columns). I can't use metachange event for this because I need to make a separate call for metadata (back-end constraint).
I make the call for metadata, I receive the metadata that I need and then create a new model with a new set of fields and a new proxy (new url). I set the model to the existing store (which is bind to my gridPanel) and then I call store.loadPage(1) (because I use a bufferedStore) and myGridPanel.reconfigure(store,meta.columns).
My problem is that store.loadPage(1) is not happening. I don't know what I am missing...
My store looks like this:
Ext.define('Foo.store.Results', {
extend: 'Ext.data.BufferedStore',
requires: [
'Foo.model.ResultRecord'
],
config: {
remoteFilter: true
},
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
pageSize: 50,
storeId: 'Results',
autoLoad: false,
model: 'Foo.model.ResultRecord',
leadingBufferZone: 50,
trailingBufferZone: 10
}, cfg)]);
}
});
I create a new model like this:
createResultModel: function(url,fields) {
console.log('createResultsModel called');
return Ext.define('Foo.model.ResultsModel'+Ext.id(), {
extend: 'Ext.data.Model',
fields: fields,
proxy: {
type: 'ajax',
url: url,
useDefaultXhrHeader: false,
reader: {
type: 'json',
rootProperty: 'data'
}
}
});
}
And I change the model and reconfigure grid like this:
myStore.setModel(me.createResultModel('resources/data/results.json',meta.fields));
myStore.loadPage(1);
resultsGrid.reconfigure(myStore,meta.columns);
Thank you!
It seems that the store.load() was called but with the wrong url.... . I don't know if that is the desired functionality but it seems that the proxy from the old model was set to the store and when I set the new model, the proxy remained the old one.

How to implement custom filter algorithm for Ext.data.Store

I want to filter an Ext store using a custom algorithm. The JSON/AJAX proxy returns >100 records and I need to reduce the number to the top-5 based on a number of criteria.
How to go about this (not the algorithm but where to trigger it)?
My current approach is to use a custom reader like so
Ext.define('MyReader', {
extend : 'Ext.data.reader.Json',
alias : 'reader.myReader',
getResponseData : function(response) {
var data = this.callParent([response]);
// algorithm
return filteredData;
}
});
Ext.define('SunApp.store.Stations', {
extend: 'Ext.data.Store',
requires: ['MyReader'],
config: {
model: 'SunApp.model.Station',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data.json',
reader: {
type: 'myReader'
}
}
}
});
but I'd much rather base the algorithm on the store model than on the raw JSON data. Hence, I'd like to filter while/after the data is loaded into the store. Note that the store is created implicitly by Ext when the list view is displayed:
Ext.define('SunApp.view.Stations', {
extend: 'Ext.List',
xtype: 'stations',
config: {
title: 'Stations',
store: 'Stations',
...
Therefore, I can't just add a function to the store that I invoke manually before it's being passed to the list.
In this case where the filter may need to traverse the store data (i.e. records) several times to reduce the full set to the desired set I believe (I'm still a Sencha rookie...) the following may be fine:
write an on-load event listener
do the magic filtering
call setData on the store passing the filtered data
Hence, instead of filtering in the reader it'd be like this:
Ext.define('SunApp.store.Stations', {
extend: 'Ext.data.Store',
config: {
model: ...,
sorters: [...],
listeners: {
load: function(store, records, success, eOpts) {
var filteredRecords = filter(records);
store.setData(filteredRecords);
}
},
proxy: ...
}
});

Resources