I have an app that allows the user to enter a set of options and then returns the result in a table. When you click the table item it push's in a panel with more detail. The problem i'm having is that it works perfect the first time but when i go to change the set of options the table items become not select-able. I am not getting any errors in the console so don't kn whats going wrong with it. The only thing i can think is it might have something to do with the below code, do i have to clear the details.setData to allow the second search results data to be pushed through?
Ext.define('FirstApp.controller.Details', {
extend: 'Ext.app.Controller',
config: {
refs: {
placesNavView:'placesContainer',
},
control: {
'placesContainer places list':{
itemtap:function(list,index,target,record){
var ref = record.get('reference');
var name = record.get('name');
var address = record.get('vicinity');
console.log(address);
console.log(name);
console.log(ref);
Ext.Viewport.setMasked({xtype:'loadmask', message:'Please Wait...'});
var proxy = {
type:'ajax',
url:'https://maps.googleapis.com/maps/api/place/details/json? reference='+ref+'&sensor=true&key=123...',
reader:{
type:'json',
rootProperty:'result'
}
}
Ext.StoreMgr.get('Details').setProxy(proxy);
Ext.StoreMgr.get('Details').load();
console.log(proxy);
var details = Ext.create('FirstApp.view.Details');
details.setData(record.data);
this.getPlacesNavView().push(details);
Ext.Viewport.setMasked(false);
}
}
}
}
});
Related
I'm trying to store my grid state using the Ext.state.CookieProvider. The problem is I can't restore sorters parameters while state itself (width, order) is restoring properly.
First I've created cookieprovider in init() method of the viewport viewcontroller:
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider', {}));
My store is set to auto load with remote sorting:
Ext.define('MyApp.requests.store.QueryRequestsGridStore', {
extend: 'Ext.data.Store',
model: 'MyApp.requests.model.QueryRequestsGridModel',
alias: 'store.queryRequestsGrid',
remoteSort: true,
autoLoad: true,
proxy: {
startParam: 'offset',
limitParam: 'limit',
url: '/requests',
noCache: false,
type: 'ajax',
reader: {
type: 'json',
rootProperty: 'data',
totalProperty: 'total'
}
},
});
Store is defined in grid using viewmodel binds:
bind: {
store: '{queryRequestsGrid}'
},
I'm loading the grid containing store from the viewport viewcontroller on button click like this:
var panelToAddName = Ext.create('MyApp.requests.view.QueryRequestsGridView', {});
var mainViewPort = Ext.ComponentQuery.query('#mainViewPort')[0];
var regionPanel = mainViewPort.down('[region=center][xtype=panel]');
regionPanel.removeAll();
regionPanel.add(panel);
Cookie contains sorters, but grid is loaded without any sort parameters.
"storeState":{"sorters":[{"root":"data","property":"date_completed","direction":"ASC"}]}}}
I've dug into the ext-all-debug.js source file and found initState() method of a 'Ext.state.Stateful' class.
initState: function() {
var me = this,
id = me.stateful && me.getStateId(),
hasListeners = me.hasListeners,
state, combinedState, i, len, plugins, plugin, pluginType;
if (id) {
combinedState = Ext.state.Manager.get(id);
if (combinedState) {
state = Ext.apply({}, combinedState);
if (!hasListeners.beforestaterestore || me.fireEvent('beforestaterestore', me, combinedState) !== false) {
plugins = me.getPlugins() || [];
for (i = 0 , len = plugins.length; i < len; i++) {
plugin = plugins[i];
if (plugin) {
pluginType = plugin.ptype;
if (plugin.applyState) {
plugin.applyState(state[pluginType], combinedState);
}
delete state[pluginType];
}
}
me.applyState(state);
if (hasListeners.staterestore) {
me.fireEvent('staterestore', me, combinedState);
}
}
}
}
},
If to log me.store from inside of this method, the store is shown in console as ext-empty-store while me is my loaded grid. Seems like state is applying before the store is properly loaded.
If to reuse the initState method inside beforerender grid event, sorters are restoring from cookie properly.
Any suggestions?
I have not worked with viewmodel binds as the sole bind between store and grid, and can't comment on whether that is supposed to work at all, or just by accident.
But I know that the viewmodel is processed very late, because the view has to be fully initialized first (including applyState), so the viewmodel can find all the components it wants to bind the listeners to.
So please try to add the store using any of the two "old-school" methods that work even without the viewmodel: store:'MyStoreId' or store:Ext.create('MyApp.store.MyStore') on the grid. That way, the store should be bound to the grid before applyState.
Furthermore, I see another issue you should address: Your store loads directly after store init. (autoLoad:true). At that time, it is not yet bound to the grid; thus, no sort/filter has been applied, which means that with remoteSort/remoteFilter enabled, you are sending too many requests to the server. I would recommend to load the store only after it has been applied to the grid (in grid.initComponent after the callParent call, or from grid.boxready listener). If you really want to use autoLoad, I'd recommend to look into setAutoLoad method
I am using Extjs 3.2grid.I have 5 Records.I am also stoping user to select multiple rows at a time.In grid i have button say approve.What i want is once user selects one record and clicks on approve the selected row coloumn "showRecord" will become 1 and remaing rows will become with showrecord:0
Here is my code
var proxy_surv = new Ext.data.HttpProxy({
type: 'ajax',
api : {
read : 'test/view.action?test='+testid_para+'&flag='+0,
create : 'test/create.action',
update : 'test/update.action',
destroy : 'test/delete.action'
}
});
var store_surv = new Ext.data.Store({
id : 'store_surv',
proxy : proxy_surv,
reader : reader,
autoSave : false
// <-- false would delay executing create, update, destroy
// requests until specifically told to do so with some [save]
// buton.
});
store_surv.on({
beforeload: {
fn: function (store, options) {
// Altering the proxy API should be done using the public
// method setApi.
store_surv.proxy.setApi('read', 'test/view.action?test='+testid_para+'&flag='+0);
}
}
});
And here is my logic
tbar: [{
iconCls: 'icon-user-add',
text: 'Approve',
handler: function(){
// Server hasn't returned yet for these two lines.
var survgrid=Ext.getCmp('grid_surv');
getstore =survgrid.getStore();
count =getstore.getCount();
var selected = survgrid.getSelectionModel().getSelected();
getstore.each(function(record){
if(parseInt(record.get('id'))==parseInt(selected.get('id')))
{
record.set('showRecord','1');
}
else
{
record.set('showRecord','0');
}
record.commit();
});
store_surv.save();
}
}
My problem is its not saving in database
don't use record.commit() it will say the record that all changes have been changed. it gets automatically called by store.sync(). remove record.commit() and it should work. you could also use 'record.save()' which will sync a single record.
I have grid panel and a button.
when i click button it will transfer data via ajax and after finish grid will reload.
I try to re-selected row (in here i give u example is first row), but anyway it's not working
Ext.Ajax.request({
url: ...,
params: {
v: ...
},
success: function(response){
grid.store.load();
grid.getSelectionModel().select(0, true); // example first row
}
})
try selecting row in callback
grid.store.load({
scope:this,
callback:function(records, operation, success){
grid.getSelectionModel().select(0, true);
}
});
or
grid.store.load(function(records, operation, success){
grid.getSelectionModel().select(0, true);
});
You can make your row selections survive across store reloads by applying the following overrides:
Ext.override(Ext.view.View, {
preserveSelectionOnRefresh: true,
constructor: function() {
this.callOverridden(arguments);
if (this.preserveSelectionOnRefresh) {
this.mon(this.getStore(), {
beforeload: this.beforeStoreLoadPreserveSelectionRoutine,
scope: this
});
}
},
beforeStoreLoadPreserveSelectionRoutine: function() {
var sm = this.getSelectionModel(),
selection = sm.getSelection(),
i = 0,
l = selection.length,
savedSelection = [];
delete sm.savedSelection;
for (; i < l; i++) {
savedSelection.push(selection[i].getId());
}
if (savedSelection.length) {
sm.savedSelection = savedSelection;
}
}
});
Ext.override(Ext.selection.Model, {
refresh: function() {
// include selections saved across store reloads
if (this.savedSelection && this.savedSelection.length) {
var rs = [],
r,
j = 0,
l = this.savedSelection.length;
for (; j < l; j++) {
r = this.store.getById(this.savedSelection[j]);
if (r) {
rs.push(r);
}
}
if (rs.length) {
this.select(rs, false, true);
}
}
this.callOverridden();
delete this.savedSelection;
}
});
What they do is just saving what was selected before reloading the store and ensuring those records are selected again after the view is refreshed. Tested on Ext JS 4.1.2.
... and if you are using a buffered store and Ext JS 4.2+, you could use the scrollTo function, which selects AND scrolls the view to your selection:
grid.store.load(function(records, operation, success){
grid.view.bufferedRenderer.scrollTo(0, true);
});
select row after loading the store by adding a callback:
grid.store.load(function(records, operation, success) {
grid.getView().select(0);
});
grid.store.load ==> grid.store.on
http://bit.ly/1iBwb2i
On response, maybe you can use a field to differentiate it :
Sencha 4.0.7: store finde
store.find(fieldName, value);
Another way, but I think it isn't work after load store, it's use:
Sencha: getLastSelected
grid.getSelectionModel().getLastSelected()
Here is a plugin the takes care of that for you:
https://github.com/roberto-rodriguez/ExtJs_GridMultipageSelectionPlugin
The plugin keeps the selection across the pages in the pagination grid. Also includes a function named: getSelection() to the grid, which returns the an array with the ids of the selected rows.
The plugin assumes there is a column with dataIndex: 'id'
In case you want to select whatever was last selected (not just the first row as shown in the accepted answer) this is the simplest I think:
grid.store.load(function() {
var view = grid.getView(),
selModel = grid.getSelectionModel(),
lastSelected = selModel.getLastSelected();
view.select(lastSelected);
});
or better, a listener for all loading done by the store in the future:
grid.store.on('load', function() {
var view = grid.getView(),
selModel = grid.getSelectionModel(),
lastSelected = selModel.getLastSelected();
view.select(lastSelected);
});
grid.store.load();
We were having the same issue on Sencha 5.0.1. We found out this can be solved by adding an idProperty to your model. After that you can just call the reload() function on the store.
In your model:
idProperty: 'yourIdentifyingProperty',
Then
yourGrid.getStore().reload();
I'm not sure if you also have to bind the selection of the grid, but if the above doesn't work you could also try that.
I have a grid that pops up an edit form with combobox. Before I show the view I load the combobox store. Then I set the values of the form using form.loadRecord(record);. This loads the primary record ok. But how do I load the associated data value that is tied to the combobox so the combobox's value is set correctly.
I know I can use setValue manually, but I guess I was thinking could be handled via a load form.
If my form has 3 fields lets say firstName lastName and then a combobox of ContactType. The firstName and lastName are in my primary record with ContactType being the associated record. If I change values in fields lastName or firstName a change is detected and the record is marked as dirty. If I change the combobox value the record is not marked as dirty. I am guessing because they are two different models. How to make it one record. I would think having a combobox on a form that has its values set from a record in a grid is common but I can't find any examples of best way to accomplish this.
Here is some code.
My json looks like this. Primary record has firstName lastName hasOne associated record is ContactType
{
"__ENTITIES":[
{
"__KEY":"289",
"__STAMP":12,
"ID":289,
"firstName":"a",
"middleName":"",
"lastName":"asd",
"ContactType":{
"__KEY":"2",
"__STAMP":4,
"ID":2,
"name":"Home"
}
}
]
}
Controller list function,edit function and updatefunction, fires when grid row is clicked
list: function () {
var mystore = this.getStore('Contacts')
mystore.proxy.extraParams = { $expand: 'ContactType'};
mystore.load({
params: {
},
callback: function(r,options,success) {
// debugger;
} //callback
}); //store.load
editContact: function (grid, record) {
//load store for combobox
var store = this.getStore('ContactTypes');
store.load({
params: {
},
callback: function(r,options,success) {
// debugger;
} //callback
}); //store.load
var view = Ext.widget('contactsedit');
var form = view.down('form')
//load primary record
form.loadRecord(record);
//load associated record
form.loadRecord(record.getContactType());
updateContact: function (button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues(),
store = this.getStore('Contacts')
if (form.getForm().isValid()) {
if (this.addnew == true) {
store.add(values);
} else {
record.set(values);
}
store.sync();
win.close();
}
}
The loadRecord(record.getContactType) is a getter to the associated data. I am able to get the associated data but not sure how to make it set the value in the combobox or how to get it to act as one record and detect changes automatically.
My Contacts Model
Ext.define('SimplyFundraising.model.Contact', {
extend : 'Wakanda.model',
requires:[
'SimplyFundraising.model.ContactType'
],
fields: ['firstName', 'middleName','lastName','ContactType.name'],
associations: [
{
type: 'hasOne',
model: 'SimplyFundraising.model.ContactType',
name: 'ContactTypes',
getterName: 'getContactType',
associationKey: 'ContactType'
}
]
});
ContactType model
Ext.define('SimplyFundraising.model.ContactType', {
extend : 'Wakanda.model',
fields: ['__KEY','name',]
});
Is this the proper way to set a value for a combobox in a form with nested data?
Should I not use associations and just put all fields in my Contact Model ie add all ContactType fields to Contact model, then data should be in the same record and change tracking would work. But this seems counter to the MVC pattern and counter to the reason for associations.
How do you guys handle this scenario, any examples would be great!
Thanks,
Dan
if your form is loading the values correctly, then all you need to do is this:
Extjs4, How to set displayField in combo editor?
I think I have a very popular problem, but not found answer for it now. :)
I got 2 similar comboboxes - at first i set my value by id - comboT.setValue("22763"); and it properly set a text value linked with this id.
At second combobox i at first reload store(jsonstore) and then set value - comboC.setValue("3"); But this combo set only ID not text value (if i open list i can see what combo properly marked text value. And after (if list simply close without select) text value properly displayed at combo.
How to solve this problem?
Thanks.
Something like this, syntax may be slightly off since I am doing it from memory:
var val = 3;
var store = comboC.getStore();
store.on("load", function() {
comboC.setValue(val);
}):
store.load();
Loading the store is asynchronous, you might want to move setting the new value into the callback: event handler of store.load({...}), because otherwise, you set the value before the store is actually loaded.
EDIT: for completeness, an example, so you have an alternative version (in some cases it might be undesireable to bind the callback to the store itself, like ormuriauga did):
var val = 3;
var store = comboC.getStore();
store.load({
callback: function() {
comboC.setValue(val);
}
});
One more example on how to set the combobox's value by searching a string in the underlying data store. I was able to code this by using the samples in these answers as a baseline:
//The store's data definition must have at least a data.id field defined
set_combobox_value_from_store = function (combobox, valueField, value) {
//Get a reference to the combobox's underlying store
var store = combobox.getStore();
store.load({
callback: function () {
//Find item index in store
var index = store.find(valueField, value, false);
if (index < 0) return;
//Get model data id
var dataId = store.getAt(index).data.Id;
//Set combobox value and fire OnSelect event
combobox.setValueAndFireSelect(dataId);
}
});
In extjs 4.1 looks like combo.setValue() works when the type of valueField in the Model is "string". this was my code
Ext.define('Model.CboObras', {
extend: 'Ext.data.Model',
idProperty: 'co_obra',
fields: [{
name: 'co_obra',
type: 'int'
}, {
name: 'nb_obra',
type: 'string'
}]
});
this does not work.
When I changed my code to this:
Ext.define('Model.CboObras', {
extend: 'Ext.data.Model',
idProperty: 'co_obra',
fields: [{
name: 'co_obra',
type: 'string'
}, {
name: 'nb_obra',
type: 'string'
}]
});
After that I use this:
var store = comboC.getStore();
store.load({
callback: function() {
comboC.setValue(val);
}
});
it now works like a charm!