I wrote my Ajax in init component and I am getting all the require data in this.store.
But I am not getting scope of store in grid where i defined. Since I am closing the bracket of Ajax Success I am not. what is the correct way to do.
My Code is :
initComponent: function() {
this.fields = [];
this.columns = [];
this.data = [];
this.store = [];
Ext.Ajax.request({
url: 'XML/1Cohart.xml',
scope: this,
timeout: global_constants.TIMEOUT,
method: "GET",
disableCaching: true,
failure: function(response) {
utils.showOKErrorMsg(sdisMsg.ajaxRequestFailed);
},
success: function(response) {
var datas = response.responseXML;
Ext.each(datas.getElementsByTagName("HEADER"), function(header) {
this.buildField(header);
this.buildColumn(header);
}, this);
Ext.each(datas.getElementsByTagName("G"), function (columnData) {
this.buildData(columnData);
this.fieldLength = this.fields.length;
this.record = [];
for (i = 0; i < this.fieldLength; i++) {
//debugger;
var fieldName = this.fields[i].name
this.record[i] = columnData.getAttribute(fieldName);
}
this.data.push(this.record);
}, this);
this.store = new Ext.data.ArrayStore({
fields : this.fields
});
this.store.loadData(this.data); // Getting correct data in this.store
},
});
In same init component in east panel i defined grid. for which column is coming but store is not getting.
Grid code is
{
xtype: 'panel',
region: "east",
header: true,
collapsible: true,
autoScroll: true,
//columnWidth: 0.5,
width: "30%",
hideBorders: true,
split: true,
items: [{
xtype: 'panel',
title: "Search Result",
height:500,
items: [{
xtype: 'grid',
itemid: 'ABC_GRID',
store : this.store,
autoHeight: true,
sm: new Ext.grid.CheckboxSelectionModel({singleSelect:true}),
frame: true,
columns : this.columns,
}]
}]
After loading the data in this.store get the grid and reconfigure its store
Ext.ComponentQuery.query("#ABC_GRID")[0].reconfigure(this.store);
For ExtJs 3
We need use Ext.getCmp() as Ext.ComponentQuery.query is not supported. Need to define id property of grid as id:ABC_GRID.
Ext.getCmp("ABC_GRID").reconfigure(this.store)
Rather than calling This.store you can call grid.getview().getStore(), you will get the store of the grid where you want to load the data.
Related
I could not paginate on the grid. I looked through their examples but encountered proxy errors. I share my own code. I will be glad if you help.
I share my codes below
Ext.QuickTips.init();
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
var grid_data_veri;
var grid_array = [];
$.ajax({
type: 'GET',
url: 'ajaxQueryData?_qid=4146&xirsaliye_dt_k='+baslangic_tarih+'&xirsaliye_dt_b='+bitis_tarih,
data: { get_param: 'value' },
dataType: 'json',
async: false,
success: function (kat, data) {
var kat_sayisi = kat.browseInfo.totalCount;
for(var i_kat = 0; i_kat < kat_sayisi; i_kat++) {
var json = {
"sira_no":sira_no ,
"branch_id":kat.data[i_kat].branch_id_qw_,
"firma": kat.data[i_kat].firma
};
grid_array.push(json);
}
grid_data_veri = JSON.stringify(grid_array);
var store = new Ext.data.JsonStore({
fields: [
{name: "sira_no", type: "int"},
{name: "branch_id"},
{name: "firma"}
]
});
// manually load local data
store.loadData(Ext.decode(grid_data_veri));
// create the Grid
var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{
id :'sira_no',
header : 'Sıra No',
width : 50,
sortable : true,
dataIndex: 'sira_no'
},
{
header : 'Şube',
width :150,
sortable : true,
dataIndex: 'branch_id'
}
,
{
header : 'Firma',
width :250,
sortable : true,
dataIndex: 'firma'
}
],
stripeRows: true,
height:395,
width: 650,
stateful: true,
stateId: 'grid'
});
grid.render('grid');
}
});
I have a grid.Panel, it is hidden by default. When I show it, it renders 100 lines and performs the function renderer, but if you call refresh() for this table, it will render only 49 lines, what do these numbers depend on and how to change them? Also wondering if there is an event when the lines are rendered to cause setLoading(false)?
grid.Panel:
extend: 'Ext.grid.Panel',
alias: 'widget.commongrid',
controller: 'commongrid-controller',
viewModel: {
type: 'commongrid-model'
},
viewConfig: {
enableTextSelection: true
},
enableColumnMove: false,
columns: [],
bind: {
store: '{commonDetailStore}'
},
createGrid: function (columns, data) {
var ctrl = this.getController();
ctrl.createGrid(columns, data);
}
Controller code:
createGrid: function (columns, data) {
var me = this,
view = me.getView(),
vm = me.getViewModel(),
store = vm.getStore('commonDetailStore');
columns = me.generateColumn(columns);
view.reconfigure(columns);
store.loadData(data);
},
generateColumn: function (columns) {
return Ext.Array.map(columns, function (column, index) {
return {
'dataIndex': column,
'text': column,
'width': 150,
'sortable': false,
'resizable': true,
'menuDisabled': true,
'renderer': 'onCommonDetailedGridColumnRenderer'
};
});
}
grid.Model:
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.commongrid-model',
stores: {
commonDetailStore: {
autoLoad: true,
proxy: {
type: 'localstorage'
},
fields: []
}
}
My field looks like this:
...
{
xtype: 'gridcolumn',
text: 'MyField',
dataIndex: 'contragent',
editor: {
xtype: 'combobox',
allowBlank: false,
displayField:'name',
valueField:'id',
queryMode:'remote',
store: Ext.data.StoreManager.get('ContrAgents')
},
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
store_ca = Ext.data.StoreManager.get('ContrAgents');
if (record.data.contragent != ''){
store_ca.load();
var contr = store_ca.getById(record.data.contragent);
//indexInStore = store_ca.findExact('id', value);
console.log(contr);
return contr.data.name;
}
}
},
...
Store 'ContrAgents' looks like this:
Ext.define('BookApp.store.ContrAgents', {
extend: 'Ext.data.Store',
model: 'BookApp.model.ContrAgents',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'app/data/Contragents.json'
}
});
The problem is that the name of the required field is not returned (contr.data.name), contr is null.
Apparently the store does not have time to load, in this case I need to load it, but store_ca.load () does not bring results.
How to load the store correctly to use
store_ca.getById (record.data.contragent); to return the name of the field?
I'm not entirely sure why you would need to use a store to populate the value in the grid's cell, because you could always just send the text value through the grid's store as opposed to the id.
You probably have a good reason for doing it, so I've revisited the fiddle and implemented it accordingly. You should be able to check it out here
The changes
../app/store/ContrAgents.js
Ext.define('Fiddle.store.ContrAgents', {
extend: 'Ext.data.Store',
model: 'Fiddle.model.ContrAgents',
autoLoad: false,
proxy: {
type: 'ajax',
url: 'Contragents.json'
}
});
../app/store/ListViewStore.js
Ext.define('Fiddle.store.ListViewStore', {
extend: 'Ext.data.Store',
model: 'Fiddle.model.ListViewModel',
autoLoad: false,
proxy: {
type: 'ajax',
url: 'List.json'
}
});
../app/view/ListView.js
Ext.define('Fiddle.view.ListView' ,{
extend: 'Ext.grid.Panel',
alias: 'widget.booklist',
itemId: 'BookList',
store: 'ListViewStore',
xtype: 'listview',
plugins: 'gridfilters',
initComponent: function() {
var me = this;
// Pin an instance of the store on this grid
me.myContrAgents = Ext.data.StoreManager.lookup('ContrAgents');
// Manually load the 'ContrAgents' first
me.myContrAgents.load(function(records, operation, success) {
// Now load the 'ListViewStore' store
me.getStore().load();
});
me.columns = [
{
header: 'ID',
dataIndex: 'id',
sortable: true,
width: 35
},
{
text: 'Контрагент',
dataIndex: 'contragent',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
if (value > 0) {
if (rec = me.myContrAgents.findRecord('id', value)) {
return rec.get('name');
}
}
return '';
}
}
];
me.callParent(arguments);
}
});
Data/List.json
"data" : [
{"id": 1, "contragent": "2"},
{"id": 2, "contragent": "3"},
{"id": 3, "contragent": "4"}
]
You are trying to query the store before it's data is actually populated. You want to avoid loading the store for each time the renderer event is triggered.
The Ext.data.Store->load function is asynchronous
See docs
store.load({
scope: this,
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
console.log(records);
}
});
Change your implementation to this and test if it works
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
store_ca = Ext.data.StoreManager.get('ContrAgents');
if (record.data.contragent != ''){
store_ca.load(function(records, operation, success) {
console.log('loaded records');
var contr = store_ca.getById(record.data.contragent);
indexInStore = store_ca.findExact('id', value);
console.log({
contr: contr,
indexInStore: indexInStore
});
});
// Not sure what you are trying to return here
// return contr.data.name;
}
}
Remote Combo in ExtJS Grid Example
I found a good example for what you are trying to accomplish here with a combo dropdown in a grid with a remote store, check out this post (you might have to register for free but the solution is worth it and I won't plagiarise it here)
Grid with combo edit widget with binding
Perhaps this could help...
Ext.define('Fiddle.view.ListView' ,{
extend: 'Ext.grid.Panel',
alias: 'widget.booklist',
itemId: 'BookList',
store: 'ListViewStore',
xtype: 'listview',
plugins: ['cellediting','gridfilters'],
initComponent: function() {
this.columns = [
{
header: 'ID',
dataIndex: 'id',
sortable: true,
width: 35
},
{
text: 'Контрагент',
width: 150,
xtype: 'widgetcolumn',
dataIndex: 'contragent',
widget: {
xtype: 'combo',
bind: '{record.contragent}',
allowBlank: false,
displayField: 'name',
valueField: 'id',
store: Ext.data.StoreManager.lookup('ContrAgents')
}
}
];
this.callParent(arguments);
}
});
I've created a script to dynamically generate a form, but I'm having problem loading the data of the nested model. I've tried loading the whole record and I've tried loading each sub store, but neither works.
I've through about using form.load(), but from my understanding that requires a proxy connection and also require to store json data inside a 'data' array.
Does anyone have any suggestions on how might I approach this problem?
<div id="view-#pageSpecificVar" class="grid-container even"></div>
<div id="button"></div>
<script>
Ext.define('HeaderForm', {
extend: 'Ext.form.Panel',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
id: Ext.id(),
defaultType: 'textfield'
});
me.callParent(arguments);
}
});
// Define our data model
Ext.define('HeaderModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'HeaderSequence', type: 'int'}
],
hasMany:[
{ name: 'Columns', model: 'ColumnModel' }
],
proxy: {
type: 'ajax',
actionMethods: { create: 'POST', read: 'GET', update: 'POST', destroy: 'POST' },
url: '#Url.Content("~/Test/Header")',
timeout: 1200000,
},
});
Ext.define('ColumnModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'ColumnWidth', type: 'float'}
],
hasMany:[
{ name: 'Fields', model: 'FieldModel'}
],
belongsTo: 'HeaderModel'
});
Ext.define('FieldModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'XType', type: 'string'},
{ name: 'FieldLabel', type: 'string'},
{ name: 'Name', type: 'string'},
{ name: 'Data', type: 'string'},
{ name: 'FieldSpecify', type: 'bool'}
],
belongsTo: 'ColumnModel'
});
var store = Ext.create('Ext.data.Store', {
storeId: 'HeaderStore',
model: 'HeaderModel',
autoDestroy: true,
listeners: {
load: function (result, records, successful, eOpts) {
//console.log(result);
var form = dynamicForm(records[0]);
form.add(submitButton);
form.render('view-#pageSpecificVar');
}
}
});
store.load();
var dynamicForm = function(record) {
var form = new HeaderForm();
var columnContainer = new Ext.widget({
xtype: 'container',
layout: 'column'
});
var formItems = new Ext.util.MixedCollection();
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.iterate(item.data, function (key, value) {
var fieldContainer = new Ext.widget({
xtype: 'container',
columnWidth: value
});
Ext.each(item.FieldsStore.data.items, function(item) {
if(item.data["FieldSpecify"]) {
fieldContainer.add(new Ext.widget({
xtype: item.data["XType"],
fieldLabel: item.data["FieldLabel"],
name: item.data["Name"],
//value: item.data["Name"]
}));
}
}, this);
columnContainer.add(fieldContainer);
}, this);
}, this);
formItems.add(columnContainer);
form.add(formItems.items);
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
form.loadRecord(fields);
});
});
//form.loadRecord(record);
return form;
};
var submitButton = new Ext.widget({
xtype: 'toolbar',
dock: 'bottom',
items:[{
xtype: 'button',
text: 'Save',
handler: function(button) {
var basic = button.up('form').form;
basic.updateRecord(basic.getRecord());
var store = Ext.StoreMgr.get('HeaderStore');
store.each(function(record) {
record.dirty = true;
});
store.sync();
}
}]
});
</script>
Update
Sorry I probably didn't made it very clear. I'm having problem loading the store data into form fields. For static forms I normally use loadRecord to load the nested model into a form, but in this case all the fields are nested in their own little model, so would there be a way to load each nested model value into their own field with loadRecord?
The HeaderModel stores field set information.
The purpose of ColumnModel is to create the container that will surround a set of fields, for styling purpose. It simply creates two columns of fields.
The FieldModel stores the field specific attributes and data.
Here's an example of response json data...
{
"HeaderSequence":1,
"Columns":[{
"ColumnWidth":0.5,"Fields":[
{"XType":"textfield","FieldLabel":"FieldA","Name":"NameA","Data":"A","FieldSpecify":true},
{"XType":"textfield","FieldLabel":"FieldB","Name":"NameA","Data":"B","FieldSpecify":true}]
},{
"ColumnWidth":0.5,"Fields":[
{"XType":"textfield","FieldLabel":"FieldA2","Name":"NameA2","Data":"A2","FieldSpecify":true},
{"XType":"textfield","FieldLabel":"FieldB2","Name":"NameB2","Data":"B2","FieldSpecify":true}]
}
]
}
Thanks
I've figure out how to load the nested model into the form. We can't simply use load or loadRecord, as by default that method tries to get a model's data and iterate through the data object and call setValues.
What I have to do is manually get the basic form element and call setValues myself to assign the values.
// loop through each field store to load the data into the form by field id
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
form.getForm().setValues([{ id: fields.data['Id'], value: fields.data['DisplayName'] }]);
});
});
To Follow up with that, a custom submit handler needs to be put in place as well.
Which loops through the store and sets the submitted value to store before sync the store.
// define form submit button
var submitButton = new Ext.widget({
xtype: 'toolbar',
dock: 'bottom',
items:[{
xtype: 'button',
text: 'Save',
handler: function(button) {
// get basic form for button
var basic = button.up('form').form;
// get form submit values
var formSubmitValues = basic.getValues();
// get header store
var store = Ext.StoreMgr.get('HeaderStore');
// loop through each field store and update the data values by id from the form
store.each(function(record) {
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
fields.data['Data'] = formSubmitValues[fields.data['Id']];
});
});
// mark the record as dirty to be sync
record.dirty = true;
});
// sync store object with the database
store.sync();
}
}]
});
Have a look at this and this examples on how to load nested data into a nested model. You will also see how to access the associated data.
I'm not sure why you use record.ColumnsStore.data.items, as if record is of HeaderModel type, you should really get the columns store via record.Columns, and then iterate that store.
Would also help to see what JSON your server returns.
I'm using Ext JS 2.3.0 and have created the search dialog shown below.
The search results are shown in a GridPanel with a single Name column, but notice that this column does not stretch to fill all the available horizontal space. However, after I perform a search, the column resizes properly (even if no results are returned):
How can I make the column display correctly when it's shown initially? The relevant code is shown below:
FV.FindEntityDialog = Ext.extend(Ext.util.Observable, {
constructor: function() {
var queryTextField = new Ext.form.TextField({
hideLabel: true,
width: 275,
colspan: 2,
});
var self = this;
// the search query panel
var entitySearchForm = new Ext.form.FormPanel({
width: '100%',
frame: true,
layout:'table',
layoutConfig: {columns: 3},
items: [
queryTextField,
{
xtype: 'button',
text: locale["dialogSearch.button.search"],
handler: function() {
var queryString = queryTextField.getValue();
self._doSearch(queryString);
}
}
]
});
// the search results model and view
this._searchResultsStore = new Ext.data.SimpleStore({
data: [],
fields: ['name']
});
var colModel = new Ext.grid.ColumnModel([
{
id: 'name',
header: locale['dialogSearch.column.name'],
sortable: true,
dataIndex: 'name'
}
]);
var selectionModel = new Ext.grid.RowSelectionModel({singleSelect: false});
this._searchResultsPanel = new Ext.grid.GridPanel({
title: locale['dialogSearch.results.name'],
height: 400,
stripeRows: true,
autoWidth: true,
autoExpandColumn: 'name',
store: this._searchResultsStore,
colModel: colModel,
selModel: selectionModel,
hidden: false,
buttonAlign: 'center',
buttons: [
{
text: locale["dialogSearch.button.add"],
handler: function () {
entitySearchWindow.close();
}
},
{
text: locale["dialogSearch.button.cancel"],
handler: function () {
entitySearchWindow.close();
}
}
]
});
// a modal window that contains both the search query and results panels
var entitySearchWindow = new Ext.Window({
closable: true,
resizable: false,
draggable: true,
modal: true,
viewConfig: {
forceFit: true
},
title: locale['dialogSearch.title'],
items: [entitySearchForm, this._searchResultsPanel]
});
entitySearchWindow.show();
},
/**
* Search for an entity that matches the query and update the results panel with a list of matches
* #param queryString
*/
_doSearch: function(queryString) {
def dummyResults = [['foo'], ['bar'], ['baz']];
self._searchResultsStore.loadData(dummyResults, false);
}
});
It's the same issue you had in an earlier question, the viewConfig is an config item for the grid panel check the docs , so it should be
this._searchResultsPanel = new Ext.grid.GridPanel({
viewConfig: {
forceFit: true
},
....other configs you need,
To be more precise the viewConfig accepts the Ext.grid.GridView configs, feel free to read the docs on that one too.
Otherwise this seems to be the only problem, and i refer the column width, not the gridpanel width. On the gridpanel you have a title and two buttons who doesn't seem to be affected. So i repeat the gridPanel's width is ok, it's the columns width issue.
Try to remove autoWidth from GridPanel configuration, because setting autoWidth:true means that the browser will manage width based on the element's contents, and that Ext will not manage it at all.
In addition you can try to call .doLayout(false, true) on your grid after it was rendered.
Try to add flex: 1 to your GridPanel