PDA

View Full Version : TabPanel (w/ TabBar) and NestedList as Content



sjh
28 Jun 2010, 1:07 PM
Is it possible to include a NestedList inside a card of a TabPanel with TabBar.

The bottom tabs are defined as:



var tabPanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
activeItem: 0,
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical',
xtype: 'button'
},
items:
[
{
title: 'Card1',
iconCls: 'time',
cls: 'shop'
},
{
title: 'Card2',
html: '<h1>Card2 Content</h1>',
iconCls: 'info',
cls: 'card3'
}
]
});


HTML works ok, but is there a config I can use to include a NestedList as the content as one card?

TommyMaintz
28 Jun 2010, 3:46 PM
Yeah, instead of html you could use items. In your case you probably want to remove the html from your card and set the xtype to 'nestedlist'.

xgdlm
28 Jun 2010, 4:28 PM
Hello,

I'm also trying to use a nestedList as a TabPanel card content with no success. If anyone has a sample code. This would be great.

Thanks in advance,

xav

xgdlm
29 Jun 2010, 2:27 AM
Actually my problem was more a CSS problem. :)

Simonhayre
30 Jun 2010, 5:34 AM
Hi there I'm working with SJH on this issue.
adding 'items' to the tabpanel did not work.
Any more ideas?

duyn
30 Jun 2010, 7:46 AM
Yeah, instead of html you could use items. In your case you probably want to remove the html from your card and set the xtype to 'nestedlist'.

I tried your advice, but it doesnt work. My problem is a little bit different. Basically, I start with a TabPanel with 2 buttons. When a button is click, the view is updated with a nestedList. The problem is the nestedList must use fullscreen:true [which overrides the TabPanel], else the nestedList does not show.


var nestedList = new Ext.NestedList({
fullscreen: true,
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
}]
})

var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
,{
title: 'Listing',
id: 'listing',
iconCls: 'favorites',
html: 'List of items',
cls: 'card2',
listeners: {activate: update},
}]
})

var update = function() {
tabpanel.insert(1, nestedList);
}

xantus
30 Jun 2010, 1:20 PM
If you're inserting the nested list into a panel with a layout (try layout: 'fit'), it will work.

TommyMaintz
30 Jun 2010, 1:25 PM
The reason it doesnt show when you dont add fullscreen true is because you have to call tabpanel.doLayout() after you have added an item to it. This renders it and lays it out.

duyn
30 Jun 2010, 3:26 PM
thanks for helps guys.



var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
,{
title: 'Listing',
id: 'listing',
iconCls: 'favorites',
html: 'List of items',
cls: 'card2',
listeners: {activate: update},
}]
})

var update = function() {
var nestedList = new Ext.NestedList({
fullscreen: true,
layout: {
type: 'fit'
},
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
}]
})
tabpanel.insert(1, nestedList);
tabpanel.doLayout();
}

I add layout type to the nestedList and run the doLayout() after adding nestedList to TabPanel but still no luck.

TommyMaintz
30 Jun 2010, 5:35 PM
I am kind of out of answers... ;)

Would it be possible to zip up your source code and send it to me at tommy@extjs.com so that I can take a look at the overall source code? That should help me figure out what the problem is.

Simonhayre
1 Jul 2010, 1:15 AM
I solved it. You were right to put the nestedlist into an item in place of HTML but we had to move the item back one level and amend the CSS.
duyn try this:



//JS

var update = function() {
var nestedList = new Ext.NestedList({
//fullscreen: true,
iconCls: 'favorites',
id:'nestedListId',
// layout: {
// type: 'fit'
// },
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
}]
})
//tabpanel.insert(1, nestedList);
//tabpanel.doLayout();
}

var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
,tabpanel]
})


At this point for me the nestedlist went massive because it was inheriting styles from the tabpanel, so I added a few changes to the custom CSS file.




/*CSS*/
#nestedListId .x-scroller-parent div *
{
font-size:18px;
}
#nestedListId
{
-webkit-transform: scale(1);
}
#nestedListId .x-scroller-parent
{
padding:0.1px;
}




I've ripped most of this from my code, I might have missed something. let me know how you get on.

duyn
1 Jul 2010, 7:42 AM
Simon,

Thank for your contribution. Your solution fixes part of my problem. I agree that by doing your way, I can display the nestedList inside a TabPanel on page load.. What I really want to do is ... when i click a TabPanel item, it should replace its current content with a nestedList. For example:
Listing button is clicked, which trigger updateContent [ generate nestedList and attempt to insert it into the TabPanel item]. I use insert and add method of a TabPanel, but it does not work. I can not find a way to replace a TabPanel item's content.


var updateContent = function() {
var nestedList = new Ext.NestedList({
fullscreen: true,
iconCls: 'favorites',
id:'nestedListId',
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
},{
text: 'Option B',
items: [{
text: 'Option B.1'
},{
text: 'Option B.2'
}]
},{
text: 'Option C',
items: [{
text: 'Option C.1'
},{
text: 'Option C.2'
}]
}]
});
//
tabpanel.insert(3, nestedList);
// tabpanel.add(nestedList);
// nestedList.doLayout();
tabpanel.doLayout();
};


var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{

title: 'Tab1',
html: '<p>Tab1 content go here</p>',
iconCls: 'info',
cls: 'card1'
}
,{
title: 'Tab2',
html: '<p>Tab2 content go here</p>',
iconCls: 'info',
cls: 'card2'
}, {
title: 'Listing',
id: 'listing',
listeners: {activate: updateContent},
iconCls: 'favorites',
cls: 'card3',
}]
});

duyn
1 Jul 2010, 7:44 AM
I am kind of out of answers... ;)

Would it be possible to zip up your source code and send it to me at tommy@extjs.com so that I can take a look at the overall source code? That should help me figure out what the problem is.

Hi Tommy,

I sent the zip file to your mailbox. Thank you.

Simonhayre
1 Jul 2010, 8:00 AM
Sounds like you and I are doing something similar,
Try something like this.


//JS
var newobjects = Array();
//loop through data from databse
for(var objectData in data )
{
newobjects.push(
{
text: objectData['text'],
title: objectData['title']//, now add more objects
//items: newobjectsChildren
}
}
var nestedList = new Ext.NestedList({
iconCls: 'favorites',
id:'nestedListId',
items: []
})

//add the objects to the nestedlist
nestedList.setList(newobjects, true);

var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
, nestedList]
})

duyn
6 Jul 2010, 7:13 AM
Hi Simon,

I understand your approach is inserting new items to a nested list, then render the tab panel. I wonder if you can update your nested list and render it after the first time ?

Stijn
6 Jul 2010, 9:50 AM
thanks for helps guys.



var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
,{
title: 'Listing',
id: 'listing',
iconCls: 'favorites',
html: 'List of items',
cls: 'card2',
listeners: {activate: update},
}]
})

var update = function() {
var nestedList = new Ext.NestedList({
fullscreen: true,
layout: {
type: 'fit'
},
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
}]
})
tabpanel.insert(1, nestedList);
tabpanel.doLayout();
}

I add layout type to the nestedList and run the doLayout() after adding nestedList to TabPanel but still no luck.


This demo give's me the error:

TypeError: Result of expression 'tabpanel' [undefined] is not an object.

Simonhayre
6 Jul 2010, 11:32 AM
Hi Simon,

I understand your approach is inserting new items to a nested list, then render the tab panel. I wonder if you can update your nested list and render it after the first time ?

I've not managed to add new items and update, but I have managed to rebuild and replace. If you find out how to insert new items without rebuilding please let us know as this would cut down on traffic.

Simonhayre
6 Jul 2010, 11:35 AM
This demo give's me the error:

TypeError: Result of expression 'tabpanel' [undefined] is not an object.

Can you post your code please.

duyn
6 Jul 2010, 11:39 AM
I've not managed to add new items and update, but I have managed to rebuild and replace. If you find out how to insert new items without rebuilding please let us know as this would cut down on traffic.

How can you rebuild and replace ?

Stijn
6 Jul 2010, 11:42 AM
Same a the code from



var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
,{
title: 'Listing',
id: 'listing',
iconCls: 'favorites',
html: 'List of items',
cls: 'card2',
listeners: {activate: update},
}]
})

var update = function() {
var nestedList = new Ext.NestedList({
fullscreen: true,
layout: {
type: 'fit'
},
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
}]
})
tabpanel.insert(1, nestedList);
tabpanel.doLayout();
}

Simonhayre
7 Jul 2010, 12:17 AM
How can you rebuild and replace ?

I placed the building of the items for the nestedlist and the call to setNestedlist() into a function and placed it out side of the onReady function. The Event Listener and the creation of the nestedlist stays in side the onReady function. I then call the function that builds and sets the nestedlist in an event listener of nestedlist, I'll try to do a working example.

Simonhayre
7 Jul 2010, 12:19 AM
Same a the code from



var tabpanel = new Ext.TabPanel({
tabBar: {
dock: 'bottom',
layout: {
pack: 'center',
}
},
fullscreen: true,
ui: 'light',
animation: {
type: 'slide',
cover: true
},
defaults: {
scroll: 'vertical'
},
items: [{
title: 'Info',
html: '<h1>Info</h1>',
iconCls: 'info',
cls: 'card1'
}
,{
title: 'Listing',
id: 'listing',
iconCls: 'favorites',
html: 'List of items',
cls: 'card2',
listeners: {activate: update},
}]
})

var update = function() {
var nestedList = new Ext.NestedList({
fullscreen: true,
layout: {
type: 'fit'
},
items: [{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
}]
})
tabpanel.insert(1, nestedList);
tabpanel.doLayout();
}

This is a suggestion not an example

Simonhayre
7 Jul 2010, 5:44 AM
Here you go.

JS CODE:

// NEED TO LOOP THROUGH NEW ITEMS AND ADD LISTENER WITIN EXTJS CODE


// Some default vars
var strDefaultTitle = 'Default Title';
var strDefaultBackTitle = 'BACK';


function getListItems(nestedList)
{
Ext.Ajax.request(
{
url : 'JsonList.php' ,
method: 'POST',
timeout: '20000',
success: function(data)
{
if(Ext.decode(data.responseText).success){
getData(data.responseText);

}else{
alert("SQL failure");

}
},
failure: function() {alert("Failed to retrieve flight list.\nCheck your connectivity.");},
});

var getData = function(data)
{
var decodedData = Ext.decode(data).listItems;

var newItems = Array();
for (var i = 0; i < decodedData.length; i++)
{
var listItem = decodedData[i];

//get children
var newItemsChildren = Array();
for (var j = 0; j < listItem['children'].length; j++)
{
var listItemChild = listItem['children'][j];
newItemsChildren.push(
{
title: listItemChild['name'],
text: listItemChild['name']
});
}

//create item and add children
newItems.push(
{
text: listItem['name'],
title: listItem['name'],
items: [newItemsChildren]
});
}

nestedList.setList(newItems, true);
}
}

// Sencha Touch:
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'img/logo.png',
icon: 'img/icon.png',
glossOnIcon: false,
onReady: function() {

var drawlist = {
afterlayout: function (nestedList)
{
var newItems = getListItems(nestedList);
},
listchange: function (nestedList, listObject)
{
// If we're returning to list. show default title, otherwise show flight title
if (listObject.title != null )
{
nestedList.toolbar.setTitle(listObject.title);
}
else
{
// returning to main list
var newItems = getListItems(nestedList);
nestedList.toolbar.setTitle(strDefaultTitle);
}

nestedList.backButton.setText(strDefaultBackTitle);
}

}


// Main list:
var NestedList = new Ext.NestedList({
toolbar: {
title:strDefaultTitle
},
listeners: drawlist,
items: [],
fullscreen: true
});
}
});



PHP CODE JsonList.php:

<?php

$objReturn = new stdClass;
$objReturn->success = true;

$objReturn->listItems = array();

for($i = 10; $i > 0; $i--)
{
$listItem = array();
$listItem['name'] = 'list'.$i;
$listItem['children'] = array();
for($j = 0; $j < 10; $j++)
{
$listItem['children'][$j]['name'] = 'child list'.($j + 1);
}

array_push($objReturn->listItems, $listItem);
}
echo json_encode($objReturn);
?>



Json source example:

{"success":true,"listItems":[{"name":"list10","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list9","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list8","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list7","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list6","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list5","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list4","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list3","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list2","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]},{"name":"list1","children":[{"name":"child list1"},{"name":"child list2"},{"name":"child list3"},{"name":"child list4"},{"name":"child list5"},{"name":"child list6"},{"name":"child list7"},{"name":"child list8"},{"name":"child list9"},{"name":"child list10"}]}]}

danvega
10 Jul 2010, 1:56 PM
Does anyone have a simple working example of this? Is it me or is everything over complicated? Why can't you just do this?


{
id:'card1',
title:'Sessions',
iconCls:'time',
items: [nestedList]
}


var nestedList = new Ext.NestedList({
fullscreen: true,
layout: {
type: 'fit'
},
items: [
{
text: 'Option A',
items: [{
text: 'Option A.1'
},{
text: 'Option A.2'
}]
},
{
text: 'Option B',
items: [{
text: 'Option B.1'
},{
text: 'Option B.2'
}]
}
]
});

TommyMaintz
13 Jul 2010, 1:18 PM
You have a fullscreen: true on your NestedList. This will render it right after instantiation. You only want to set fullscreen true on the outermost container or panel in your app. All you other components should be item and managed by the layouts of their containers.



var panel = new Ext.TabPanel({
fullscreen: true,
items: [{
id: 'card1',
title: 'Sessions,
iconCls: 'time',
items: [{
text: 'Option A',
items: [
{text: 'Option A.1'},
{text: 'Option A.2'}
]
}, {
text: 'Option B',
items: [
{text: 'Option B.1'},
{text: 'Option B.2'}
]
}]
}]
});


Does that do what you want?