PDA

View Full Version : Dynamically Add a Tab (Using seperate JS files)



schone
14 Sep 2008, 6:27 AM
Hi all,

After reading Saki's tutorials on how to organize your application using pre-configured classes I have hit a snag.

I have a Viewport :
North : Toolbar (Menu with Items)
Center : TabPanel
South : Toolbar
East : PanelI'm trying to add a Tab to the Center region (TabPanel) when you click on a certain item from the Menu on the Toolbar - the problem is that they both sit in seperate .js files as pre-conifg classes (see below). I'm using the getCmp() function but seem to be getting this error:


Error: Ext.getCmp("center-panel") has no propertiesLayout.Center.js (Center TabPanel)

So on to my code:



Ext.namespace('App', 'App.Layout', 'App.Layout.Center');

App.Layout.Center = Ext.extend(Ext.TabPanel, {
id: 'center-panel',
deferredRender: false,
layoutOnTabChange: true,
activeTab: 0,
enableTabScroll: true,
border: true,

initComponent: function(){

Ext.apply(this, {
items: [{
id: '00',
title: 'Home',
closable: false
}]
});

App.Layout.Center.superclass.initComponent.apply(this, arguments);
},

onRender: function(){
App.Layout.Center.superclass.onRender.apply(this, arguments);
}
});

Ext.reg('tabCenter', App.Layout.Center);


Layout.North (North Panel with Toolbar) - Code with error in Bold



Ext.namespace('App', 'App.Layout', 'App.Layout.North');

App.Layout.North = Ext.extend(Ext.Toolbar, {
id: 'north-panel',
border: false,

actions: {
logout: null,
addtab: null,
sports: null,
},

initComponent: function(){

// init actions
this.actions.logout = new Ext.Action({
text: 'Logout',
tooltip: 'Logout from App 2.0',
id: 'tbLogout',
handler: this.onLogout
});

this.actions.sports = new Ext.Action({
text: 'Sports',
tooltip: 'Manage Sports',
id: 'tbSports',
handler: this.addTab('01')
});

Ext.apply(this, {
items: [{
id: 'NavMenuAdmin',
text: 'Adminstration',
menu: [this.actions.sports, {
id: 'tbTeams',
text: 'Teams'
}, {
id: 'tbGroups',
text: 'Groups'
}, {
id: 'tbStaff',
text: 'Staff'
}, {
id: 'tbAthletes',
text: 'Athletes'
}]
}, '->', this.actions.logout]
});

App.Layout.North.superclass.initComponent.apply(this, arguments);

},

onRender: function(){
App.Layout.North.superclass.onRender.apply(this, arguments);
},

onLogout: function(){
Ext.MessageBox.confirm('Confirm', 'Are you sure you want to logout?', function(btn, text){
if (btn == 'yes') {
Ext.MessageBox.wait('Logging you out...', 'Please wait!');
Ext.Ajax.request({
params: {},
callback: function(options, bSuccess, response){
window.location = window.location;
}
});
}
});
},
addTab: function(){
Ext.getCmp('center-panel').add({
title: 'Test',
id: '01',
closable: true
}).show();
}
});

Ext.reg('tbNorth', App.Layout.North);
index.html



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Beta - &copy 2008</title>

<!-- Core ExtJS Libs -->
<link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" />
<!-- <link rel="stylesheet" type="text/css" href="ext/resources/css/xtheme-gray.css" /> -->
<script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext/ext-all.js"></script>

<!-- App Modules -->
<script type="text/javascript" src="js/layout/Layout.Center.js"></script>
<script type="text/javascript" src="js/layout/Layout.East.js"></script>
<script type="text/javascript" src="js/layout/Layout.North.js"></script>
<script type="text/javascript" src="js/layout/Layout.js"></script>

</head>
<body>
</body>
</html>
Hopefully someone can help?

Thank you in advance!

evant
14 Sep 2008, 6:33 AM
Your handler is incorrect. You're actually executing addTab, instead of passing a reference to the method.

You want to do something like this:



handler: this.addTab.createDelegate(this, ['01'], false)


See http://extjs.com/deploy/dev/docs/?class=Function&member=createDelegate

schone
14 Sep 2008, 6:51 AM
Thanks for such a quick reply!

Evant,

I also need to load components into this Tab (Grid, Tree and Form) using JSON from server-side.

Do you suggest I create a pre-config class for the components and add it to the tab panel by using xtype?

Thanks!

evant
14 Sep 2008, 6:56 AM
You could do something like this:



Ext.override(Ext.Container,
{
addRemote: function(url, params)
{
Ext.Ajax.request(
{
url: url,
params: params,
scope: this,
success: function(response) { this.add(Ext.decode(response.responseText)); }
}
);
}
}
);

schone
14 Sep 2008, 2:03 PM
Hi Evant,

I have read through the docs in trying to understand what you have done here


Ext.override(Ext.Container,
{
addRemote: function(url, params)
{
Ext.Ajax.request(
{
url: url,
params: params,
scope: this,
success: function(response) { this.add(Ext.decode(response.responseText)); }
}
);
}
}
);

Do you mind explaining exactly what this does?

Kind Regards
schone

evant
14 Sep 2008, 2:57 PM
Ext.override(Ext.Container, //add new methods to container
{
addRemote: function(url, params) //add a method called addRemote
{
Ext.Ajax.request( //make an ajax request to the server
{
url: url,
params: params,
scope: this,
success: function(response) { this.add(Ext.decode(response.responseText)); }
//get the response as text, eval it, then call add. The response from the server
//should be something you would normally pass to add.
}
);
}
}
);

schone
14 Sep 2008, 3:44 PM
So just to clarify the 'URL' will contain the script for what ever element I need in the TabPanel.

For example:


Ext.override(Ext.Container, //add new methods to container
{
addRemote: function(url, params) //add a method called addRemote
{
Ext.Ajax.request( //make an ajax request to the server
{
url: datagrid.url,
params: 'staff',
scope: this,
success: function(response) { this.add(Ext.decode(response.responseText)); }
//get the response as text, eval it, then call add. The response from the server
//should be something you would normally pass to add.
}
);
}
}
);


Where datagrid.url (for example) is:



Ext.onReady(function() {
var myData = [
['Apple',29.89,0.24,0.81,'9/1 12:00am'],
['Ext',83.81,0.28,0.34,'9/12 12:00am'],
['Google',71.72,0.02,0.03,'10/1 12:00am'],
['Microsoft',52.55,0.01,0.02,'7/4 12:00am'],
['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']
];

var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(myData),
reader: new Ext.data.ArrayReader({id: 0}, [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
])
});
ds.load();

var colModel = new Ext.grid.ColumnModel([
{header: "Company", width: 120, sortable: true, dataIndex: 'company'},
{header: "Price", width: 90, sortable: true, dataIndex: 'price'},
{header: "Change", width: 90, sortable: true, dataIndex: 'change'},
{header: "% Change", width: 90, sortable: true, dataIndex: 'pctChange'},
{header: "Last Updated", width: 120, sortable: true,
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'}
]);

var grid = new Ext.grid.Grid('grid-example', {ds: ds, cm: colModel});
grid.render();
grid.getSelectionModel().selectFirstRow();
Ext.get('grid-example').show();
});


So that should add a grid into the TabPanel?

evant
14 Sep 2008, 4:10 PM
No, for a number of reasons:

1) The document is already ready, so onReady won't run.
2) You're trying to render the grid. If you're adding an item to a container, you should just call the add method, you only render the outermost container.
3) The code there is pretty complicated, just try and make it work for something simple first. I'd suggest you using inline definitions if you're going to do it like that, eg:



{
xtype: 'grid',
title: 'foo',
colModel: new Ext.grid.ColumnModel(....),
store: new Ext.data.Store(.....)
}

mjlecomte
14 Sep 2008, 4:23 PM
FYI, there is a remoteload directory in the examples that illustrates this concept.

http://extjs.com/deploy/dev/examples/remoteload/remoteload.php

pgraju
14 Sep 2008, 7:14 PM
Great post! Helped me clear stuff up!

schone
14 Sep 2008, 7:24 PM
Thanks evant and mjlecomte but I'm still stuck on how this work design/structure wise.

I think I should of explained how I want it laid out, when a new Tab is added I want to add to the Tab Panel :

New Tab Panel
..L Viewport
......L West Region
......L Tree based on JSON
..L Center Region
......L Form based on handler from Tree

At the moment I have sepearated my application is seperate .JS files as pre-configured classes.

My question is - Would I create a new .JS file with all the components in it (stated above) as a pre configured class and add it to the new Tab Panel?

If so would using the Override and addRemote function you specified work this way?

Sorry to sound repetitive I just want to make sure I'm structuring my application properly!

mjlecomte
15 Sep 2008, 4:51 AM
Did you look at the example I pointed out to you?

schone
15 Sep 2008, 5:21 AM
Yes and after much more investigation it all makes sense - Thanks!

mjlecomte
15 Sep 2008, 5:31 AM
Ok, good. If you now understand it, maybe you can post answers to your own questions here so someone else coming across your thread can get your perspective on it in case the other suggestions above may not be phrased in a way you understood, etc. The point is, "I figured it out" doesn't really help the next guy too much.

schone
15 Sep 2008, 5:47 AM
mjlecomte,

I may off spoken to soon, I'm still unsure on how to integrate this into my preconfigured class function which creates the new TabPanel:



addTab: function(){
Ext.getCmp('center-panel').add({
title: 'Test',
id: '01',
closable: true
}).show();
}
How would you intergrate the Ext.ux.ComponentLoader into this function?

Once I have got a working solution on my end I will no hesitate to come back and post all the code to the solution :D

Thanks again!

mjlecomte
15 Sep 2008, 7:08 AM
Seems like you are reversing. You pass configs to the component loader, not the other way around. evant's way is simplified if you want to go that route. His way might be easier to get it working, then decide if you want to abstract it further using the component Loader example. There's also some ux's for this purpose as well.

murkrishna
14 Jun 2010, 10:03 PM
FYI, there is a remoteload directory in the examples that illustrates this concept.

http://extjs.com/deploy/dev/examples/remoteload/remoteload.php


I was trying to load this URL but it is not working.

Can anyone help me in this ex.

regards
Murali