Facing problem on Window Recreating with grid in Extjs-4 - extjs

I need to render grid component with in the window(with close action destroy) so that i need to create new window and grid component instead of hide and show.
My code is working fine for the first time render but after closing window , i am unable to create it again, getting issue on layout.js
Line: 150
Error: Type mismatch.
************ getting issue in the below method and "dom" is undefined*********
moveItem : function(item, target, position) {
// Make sure target is a dom element
target = target.dom || target;
if (typeof position == 'number') {
position = target.childNodes[position];
}
target.insertBefore(item.el.dom, position || null); //dom is undefined
item.container = Ext.get(target);
this.configureItem(item);
this.childrenChanged = true;
}
************
My controller and view of(grid and window) i have attached .Please identify where i am going wrong
************
Code:
**************************************************************************
Window Controller
**************************************************************************
Ext.define('Adapt.controller.versionManager.verManWinCont', {
extend : 'Ext.app.Controller',
views : ['versionManager.verManWinView'],
init : function() {
this.control({
'verManWindow' : {
afterrender : this.verManWindowAfterRender
}
});
},
verManWindowAfterRender : function(win, options) {
});
**************************************************************************
window View
**************************************************************************
Ext.define('Adapt.view.versionManager.verManWinView' ,{
extend: 'Ext.window.Window',
requires: ['Adapt.controller.versionManager.versionCont','Adapt.view.versionManager.versionGrdView', 'Adapt.store.versionManager.versionStor'],
alias : 'widget.verManWindow',
constructor: function (config) {
this.callParent([config]);},
layout: 'fit',
closeAction :'destroy',
items: [{xtype: 'versionGrd'}],
autoShow :true,
width : 580,
height : 338,
closable : true,
plain : true
});
**************************************************************************
Grid Controller
**************************************************************************
Ext.define('Adapt.controller.versionManager.versionCont', {
extend : 'Ext.app.Controller',
views : ['versionManager.versionGrdView'],
stores : ['versionManager.versionStor'],
models : 'Adapt.model.versionManager.versionModl',
init : function() {
debugger;
this.control({
'versionGrd' : {
itemdblclick : this.versionGridDoubleClick,
afterrender : this.versionGridAfterRender
}
});
},
versionGridAfterRender : function(grid, options) {debugger;
}
});
**************************************************************************
Grid View
**************************************************************************
Ext.define('Adapt.view.versionManager.versionGrdView' ,{
extend: 'Ext.grid.Panel',
requires: ['Ext.grid.*','Adapt.view.versionManager.versionCreateView'],
alias : 'widget.versionGrd',
store: 'versionManager.versionStor',
columns:[
{header: 'Name', dataIndex: 'versionName', flex: 1},
{header: 'State', dataIndex: 'versionState', flex: 1}
],
constructor: function (config) {debugger;
this.callParent([config]);},
dockedItems: []
});
************************************************************************
(creating and showing in this handler)
In viewport Toolbar button handler(Controller)
this.getController('versionManager.verManWinCont');
this.getController('versionManager.versionCont');
new Adapt.view.versionManager.verManWinView();//.show();
Thanks for your time
vinod.P

I had exactly the same problem and solved it by changing the component creation to factory functions.
The reason is that objects in JavaScript are passed by reference, so in the snippet below every grid instance shares the same columns object:
Ext.define('Adapt.view.versionManager.versionGrdView' ,{
extend: 'Ext.grid.Panel',
columns:[
{ header: 'Name', dataIndex: 'versionName', flex: 1 },
{ header: 'State', dataIndex: 'versionState', flex: 1 }
]
});
With the factory function approach you create the grid view like this:
Ext.define('Adapt.view.versionManager.versionGrdView' ,{
extend: 'Ext.grid.Panel',
initComponent: function() {
config = Ext.apply({}, { items: this.buildColumns() });
Ext.apply(this, Ext.apply(this.initialConfig, config));
this.callParent();
}
buildColumns: function() {
return [
{ header: 'Name', dataIndex: 'versionName', flex: 1 },
{ header: 'State', dataIndex: 'versionState', flex: 1 }
]
});
Now every new instance get its own copy of the columns array, which solves the problem that a part of the configuration has been destroyed. As a nice side effect, I also noticed that the startup of the application has reduced since I use only factory methods.

Check your Column array which is sent to reconfigure.

Related

Define getRowClass function in the controller

I'm using getRowClass function for custom grid row styling. In a panel component I have 2 similar grids which should have the same getRowClass logic. I would like to define the function body in the controller binded to the parent component. Below I placed some test code that illustrates the problem. In the example getRowClass is set to point to color function defined in the main controller, however this function cannot be seen in this scope. I don't have much experience in extJS and I don't know how to solve this kind of scope problems, any help will be appreciated.
Ext.define('Test.controller', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
color : function(row,index){
return 'green-row';
}
});
Ext.onReady(function() {
win = new Ext.Window({
title:'Test',
layout:'fit',
width:400,
closeAction:'close',
target : document.getElementById('buttonId'),
plain: true,
controller: 'main',
items: [{
xtype: 'grid',
store: Ext.create("testApp.store.Objects"),
selType: 'checkboxmodel',
columns : [{
text : 'Column1',
dataIndex : 'Column1'
},{
text : 'Column2',
dataIndex : 'Column2'
},{
text : 'Column3',
dataIndex : 'Column3'
}],
viewConfig : {
getRowClass : 'color'
}
}]
});
Ext.create('Ext.Button', {
renderTo: Ext.getElementById('buttonId'),
text: 'Click Me',
listeners: {
click: function() {
win.show();
}
}
});
});
All config objects are only relevant at instantiation time of a class and don't have any effect afterwards.
You can resolve you issue like this:
listeners : {
afterrender: function(p){
p.getView().getRowClass = this.up('window').getController().color;
}
}

Read text file into the text area in extjs

I have mail.txt on my local machine and i want to display it on the UI using extjs. I created a textarea and want to import mail.txt into it.
Ext.define('com.company.view.dashboard.Dashboard', {
extend: 'Ext.panel.Panel',
alias: 'widget.dashboard',
layout: 'fit',
iconCls: 'dashboard-tree',
initComponent: function(config) {
Ext.apply(this, {
items: [
{
xtype: 'fieldcontainer',
fieldLabel: 'P&L',
labelWidth: 100,
layout: 'hbox',
items: [{
xtype: 'textarea',
flex: 1
}]
}
]
});
this.callParent(arguments);
}});
Here If you want to Display text file in UI then what I will suggest you is put you text content in to JSON format and then on top of window or Panel you can display that.
In This example I am displaying on window. You can make as per your requirment.
Here is MyMessage function which can take the response and then display on MyMessageWindow .
MyMessage : function(){
var me = this;
Ext.Ajax.request({
url : URL of your JSON
method : 'GET',
dataType:'json',
scope : me,
headers : {
"Accept" : "application/json; charset=utf-8"
},
success : function (response, args) {
var data = Ext.decode(response.responseText);
var Msgtext = data.R.MSG; // This is depend on how you binding data in JSON.
me.MyMessageWindow(Msgtext);
}
});
},
MyMessageWindow : function(Msgtext){
var FailedMsgShow = function (text) {
Ext.create({
xtype: 'window',
title: 'P&L',
width: 600,
height: 450,
html:text,
scrollable: true,
}).show();
};
FailedMsgShow('<text style="color:green;">'+Msgtext+'</text>');
},
Note : You can display on any component like panel. I just suggesting you to put on window. you can make on panel as well instead of fieldContainer.

ExtJS button handler not working

My ExtJS button's handler is not invoked after clicking. Now the code looks like this.
Ext.define('EDS.view.selector.Container', {
extend: 'Ext.form.Panel',
alias : 'widget.selectorcontainer',
title: 'Selector_V2',
renderTo: 'input-div',
layout: 'fit',
height: '100%',
items: [
{
xtype: 'tabpanel',
defaults: {
bodyPadding: 10
},
}
],
buttons: [
{
text: 'Reset',
handler: function(){
console.log("Reset");
this.up('form').getForm().reset();
}
},
{
text: 'Add to constrain',
handler: this.addConstrain,
}
],
/*
* Logic for button "Add to constrain"
*
* Adds an entry into the constrain list describing a person, cost center or an application
*/
addConstrain: function(button, event){
console.log('Add_to_constrain clicked');
}
});
Originally this 'selectorcontainer' was put diretly in my app.js. But I extracted it into a stand-alone view. Before the extraction, it works perfect but now it is not working.
BTW, I've two buttons and the first "reset" works fine. So I'm wondering if there's anything wrong with "this.addConstrain" related to scoping.
You're right, it is a scoping issue - this is not the class you're defining; it's the scope at the time the Ext.define function is called (likely window). There are a few ways to handle this. The easiest (in my opinion) is to change your handler to work similarly to your reset handler:
{
text: 'Add to constrain',
handler: function(btn, e) {
//'this' is now the button
this.up('selectorcontainer').addConstrain(btn, e);
}
}
You could also add the buttons as part of the initComponent function instead of defining them as part of the Ext.define config.
initComponent: function() {
//'this' is now the selector container
this.buttons = [{
text: 'Reset',
handler: function(){
console.log("Reset");
this.up('form').getForm().reset();
}
}, {
text: 'Add to constrain',
handler: this.addConstrain
}];
this.callParent();
}
The proper way to design your class is like this. You apply your config settings to the object before you do the callParent.
Ext.define('EDS.view.selector.Container', {
extend: 'Ext.form.Panel',
alias : 'widget.selectorcontainer',
title: 'Selector_V2',
renderTo: 'input-div',
layout: 'fit',
height: '100%',
initComponent: function() {
Ext.applyIf(this, {
items: [
{
xtype: 'tabpanel',
defaults: {
bodyPadding: 10
}
}
],
buttons: [
{
text: 'Reset',
scope: this, // <--- scope to form panel
handler: function(){
console.log("Reset");
this.getForm().reset();
}
},
{
text: 'Add to constrain',
scope : this, // <--- scope to form panel
handler: this.addConstrain
}
]
});
this.callParent(arguments);
}
/*
* Logic for button "Add to constrain"
*
* Adds an entry into the constrain list describing a person, cost center or an application
*/
addConstrain: function(button, event){
console.log('Add_to_constrain clicked');
}
});

Using single data store for single grid instance which is used everywhere in extjs

SCENARIO
I am having a gridpanel(say grid),which is been used everywhere in my application.Suppose components (panel1 and panel2) are using grid.This grid is using a store(store1).I want to update grid in panel1 without updating grid in panel2.
MY PROBLEM
I dont want to use different stores for grid in panel1 and panel2.
Is their any way this could be achieved.
I tried binding store(with new data) to grid in panel1.But grids in both panel1 and panel2 are getting updated.
If I was not clear enough,Please let me know.Please help me resolve this.Thnks a lot.
**For reference**
/*my grid*/
Ext.define('APP.view.mygrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.mygrid',
store:'store1',
columns: [ ... ]
/*my panels*/
{
xtype:'panel',
items:[
{
xtype :'mygrid',
}
],
xtype:'panel',
items:[
{
xtype :'mygrid',
}
],
}
I assume that you update your grid by some local changes in the store, and you do not make a call to your web service. Then you can try doing this:
store.suspendEvents(false); // false: do not queue events
// do some data changes now
store.resumeEvents();
grid.getView().refresh(); // only on the first grid
You can create the store for your second panel, so try this:
var secondStore=Ext.create('your_store');
items: [
{
xtype: 'gridpanel',
title: 'grid1',
store: 'your_store'
},{
xtype: 'gridpanel',
title: 'grid2',
store: secondStore
}
]
I have resolved this by creating a instace of the store each time when
the grid is called.Please have a look :
initComponent : function() {
this.items = [
{
xtype : 'myPanelgrids'
name : 'panel1' // this is the extra config to identify the grid in added in my panel1
}
];
this.callParent();
},
listeners: {
render: function(){
var store = Ext.create('Ext.data.Store',
{
model: 'App.model.MyModel',
autoLoad: true,
proxy: {
type: 'ajax',
url:'app/data/configdata.json',
reader: {
type: 'json',
root : 'myroot'//maintained a json property file with different roots for grids in panel1 and panel2
}
}
}
);
this.down('grid').reconfigure(store);
}
}
I am updating the store of particular grid from my controller.

Define listeners in controller ExtJS

I have got the tabpanel - it's the main form (view).
In this tabpanel I define the different tabs - xtype:'panel'.
So, I have one main(controller) , main view and some tabs views.
The tab's views are referenced in main view.
I want to define listener of activate event of some child's panel in main controller.
How can I do that?
the main controller :
Ext.define('KP.controller.account.apartment.Main', {
extend: 'Ext.app.Controller',
views: ['account.apartment.Main',
'account.apartment.Requisites'
],
models: ['account.apartment.Requisites'
],
stores: ['account.apartment.Requisites'
],
init: function () {
}
});
The main view:
Ext.define('KP.view.account.apartment.Main', {
extend: 'Ext.window.Window',
alias: 'widget.ApartmentData',
height: 566,
width: 950,
activeItem: 0,
layout: {
type: 'fit'
},
autoShow: false,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'tabpanel',
activeTab: 0,
deferredRender: true,
items: [
{
xtype: 'RequisitesApartment'
}
]
}
]
});
me.callParent(arguments);
}
});
The child panel RequisitesApartment (view):
Ext.define('KP.view.account.apartment.Requisites', {
extend: 'Ext.panel.Panel',
alias: 'widget.RequisitesApartment',
id: 'panel_accountrequisites',
height: 350,
width: 1124,
autoScroll: true,
layout: {
type: 'fit'
},
listeners: {
activate: function () {
....load data....
...this listeners I want to push in 'main' controller...
}
},
initComponent: function () {
var me = this;
var grid_store = Ext.create('KP.store.account.apartment.Requisites');
Ext.applyIf(me, {
dockedItems: [
{
xtype: 'gridpanel',
height: 260,
autoScroll: true,
dock: 'bottom',
store: grid_store,
id: 'r_gridFlatParams',
forceFit: true,
columns: [
...some columns....
],
viewConfig: {
}
}
]
});
me.callParent(arguments);
}
});
Register it directly as control within the responsible controller
Here is a example with a working query. For sure you just will need the query, but I think it's a good example. The custom cfg property ident make it easy find each tab. As in the example below you will have specify a tabConfig within each panel and define the ident there.
Ext.create('Ext.tab.Panel', {
width: 400,
height: 400,
renderTo: document.body,
items: [{
title: 'Foo',
tabConfig: {
ident: 'foo'
},
}, {
title: 'Bar',
tabConfig: {
ident: 'bar',
title: 'Custom Title',
tooltip: 'A button tooltip'
}
}]
});
console.log(Ext.ComponentQuery.query('tabpanel tabbar tab[ident=foo]')[0]);
console.log(Ext.ComponentQuery.query('tabpanel tabbar tab[ident=bar]')[0]);
Another way is to use css id's which can be queried like '#my-name' but I recommend to use a custom one as in the example above
Well, I should put this code in 'main'(controller):
this.control({
'ApartmentData tabpanel RequisitesApartment': {
activate: function () {
console.log('hello!');
}
}
});
The problem was in wrong selector , that I used.
The correct selector is :
'ApartmentData tabpanel RequisitesApartment'
There 'ApartmentData'(define like a alias: 'widget.ApartmentData') - is the 'window' xtype -the main form.
tabpanel - panel with tabs in 'window', and 'apartServList'(define like alias: 'widget.RequisitesApartment') - the some panel.
Thanks for sra!
the correct thing to do is to pass a config object to the member function control into controller init function. From Sencha documentation : The control function makes it easy to listen to events on your view classes and take some action with a handler function.
A quick example straight from extjs docs:
Ext.define('MyApp.controller.Users', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
console.log('The panel was rendered');
}
});
Hope this helps.
Cheers

Resources