PDA

View Full Version : Wrapping a NestedList Component



fetimo
26 May 2011, 7:56 AM
Hi there,

I have a NestedList component and am trying to wrap it in a TabPanel to have a constant tabBar at the bottom of the app.

I have an app.js file that just instantiates the Viewport, you can see my current implementation below.



app.views.List = Ext.extend(Ext.NestedList, {
id: 'list',
title: 'Categories',
store: app.event_store,
useTitleAsBackText: false,
toolbar: {
items: [
{xtype: 'spacer'},
{xtype: 'button', ui: 'confirm', hidden: true, text:'Attend',
handler: function() {
//add to list of events being attended
}
}
]
},
});

app.views.Wrapper = new Ext.TabPanel({
id: 'listwrapper',
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
items: [
{
iconMask: true,
title: 'Calendar',
iconCls: 'calendar2'
},
{
title: 'Edit',
iconCls: 'calendar_add'
}
]
});

app.views.Viewport = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
items: [app.views.Wrapper, app.views.List]
});


All this achieves however, is the tabBar at the bottom of the screen, the NestedList is nowhere to be seen :(

Can anyone illuminate why this is the case? I'm at my wits end!

Many thanks.

nelstrom
26 May 2011, 11:09 AM
As it stands, your nested list is not wrapped inside the TabPanel. It's in the items list for the Viewport. To wrap it in the TabPanel, you'll want to add it to the Wrapper's items list. But there's something else that you need to do first.

The `app.views.List` variable contains a reference your subclass of the NestedList component. That's not the same thing as an actual instance of the list. After you've created a subclass, you should register an xtype for it. In your case, this should do it:


app.views.List = Ext.extend(Ext.NestedList, {
// configuration goes here...
});
Ext.reg('myNestedList', app.views.List);

Then you can add an instance of your NestedList to the `Wrapper` TabPanel by adding an object with the xtype that you've just created:


app.views.Wrapper = new Ext.TabPanel
// more configuration...
items: [
{
iconMask: true,
title: 'Calendar',
iconCls: 'calendar2'
},
{
title: 'Edit',
iconCls: 'calendar_add'
},
{
xtype: 'myNestedList'
}
]
});

Finally, your Viewport contains raw configuration which should really be wrapped inside of an `initComponent` function call. I suggest the following instead:


app.views.Viewport = Ext.extend(Ext.Panel, {
initComponent: function() {
Ext.apply(this, {
fullscreen: true,
layout: 'card',
items: [app.views.Wrapper]
});
app.views.Viewport.superclass.initComponent.apply(this, arguments);
}
});

You should follow the same pattern when you subclass the NestedList, but I'll leave you to figure out how to do that.

fetimo
26 May 2011, 11:26 AM
Hi Drew,

Thanks very much for replying so helpfully :).

I managed to get it working but it was more luck than anything else. I'll put into practice your suggestions, and thanks for clarifying the difference between extending a class and instantiating a new instance of that class, it now makes a lot more sense!

All the best,
fetimo

fetimo
28 May 2011, 5:43 AM
Just a quick update, I implemented nelstrom's suggestions and my code now works thusly:


Schedlr.views.List = Ext.extend(Ext.NestedList, {
initComponent: function() {
Ext.apply(this, {
id: 'list',
title: 'Events',
iconCls: 'calendar_add',
layout: 'card',
store: Schedlr.stores.event_store,
useTitleAsBackText: false,
toolbar: {
items: [
{xtype: 'spacer'},
{xtype: 'button', ui: 'confirm', hidden: true, text:'Attend',
handler: function() {
//add to list of events being attended
console.log('clicked');
}
}
]
},
getDetailCard: function(item, parent) {
var itemData = item.attributes.record.data,
parentData = parent.attributes.record.data,

detailCard = new Ext.Panel({
scroll: 'vertical',
styleHtmlContent: true,
tpl: ["<h2>{text}</h2>","{info}"],
title: 'Event'
});

if(parentData.text.length > 6){
this.backButton.setText('Back');
} else {
this.backButton.setText(parentData.text);
}

//show the attend button when on leaf, hide when back button is tapped
var interceptAndHide = function() {
this.up('toolbar').getComponent(2).setVisible(false);
}
this.toolbar.getComponent(2).setVisible(true);
this.backButton.on('tap', interceptAndHide);

detailCard.update(itemData);
return detailCard;
}
});
Schedlr.views.List.superclass.initComponent.apply(this, arguments);
}
});

Ext.reg('eventsList', Schedlr.views.List);

var dateSelector = new Ext.SegmentedButton({
margin: '15 0 0 0',
items: [
{
text: '3/9',
pressed: true
},
{
text: '4/9'
},
{
text: '5/9'
},
{
text: '6/9'
},
{
text: '7/9'
}
]
});

Schedlr.views.Itinerary = Ext.extend(Ext.Panel, {
title: 'Itinerary',
iconCls: 'calendar2',
layout: 'vbox',
scroll: 'vertical',
dockedItems: [
{
dock: 'top',
xtype: 'toolbar',
ui: 'light',
title: 'Your Itinerary'
}
],
items: dateSelector
});

Ext.reg('itineraryView', Schedlr.views.Itinerary);

Schedlr.views.Wrapper = new Ext.TabPanel({
id: 'listwrapper',
layout: 'fit',
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
items: [
{
xtype: 'itineraryView'
},
{
xtype: 'eventsList'
}
]
});

Schedlr.views.Viewport = Ext.extend(Ext.Panel, {
initComponent: function() {
Ext.apply(this, {
fullscreen: true,
layout: 'card',
items: [Schedlr.views.Wrapper]
});
Schedlr.views.Viewport.superclass.initComponent.apply(this, arguments);
}
});


Could someone tell me the advantage of wrapping the config code in initComponent? Is it better for memory or what?

Many thanks once again Drew :)