Dynamic Navigation Pane Push Pages

That is somewhat of a tongue twister and it all came about because of a question on a forum.  The CrackBerry.com forums has a section for new developers, which is always a nice thing to have.  The poster is apparently trying to create an app to serve up radio stations (I think) and he wants to provide a Page for each station and also provide the list of stations through an xml file.  On the main page, he wants to display a ListView with links to the secondary Pages.

Normally, I would just create ComponentDefinition for each Page and then Push the Page by calling that definition.

Something like this.

NavigationPane {
id: nav
Page {
titleBar: TitleBar {
title:  qsTr(Qt.pageTitle) + Retranslate.onLocaleOrLanguageChanged
}
Container {
ListView {
id: mainList
dataModel: XmlDataModel {source: "main.xml"}
listItemComponents: [
ListItemComponent {
type: "item"
StandardListItem {
title: ListItemData.title
description: ListItemData.text
imageSource: ListItemData.image
}
}
]
onTriggered: {
nav.push(myOtherPageDef.createObject());

}
}
}
}
attachedObjects: [
// Definition of the second Page, used to dynamically create the Page above.
ComponentDefinition {
id: myOtherPageDef
MyOtherPage{}
}
]
}


 

 

Doing it this way helps when trying to pass things from the main navigation to and fro from the pushed Pages.  But the original poster had other ideas on what he wanted to do and it helped me figure out another way to push Pages.

The key to pushing the Page is still the ComponentDefinition.  But, since the actual Page isn’t defined in the Component Definition, that needs to be added before the ComponentDefinition is created.  The file name of the Page, plus title and image icon is contained in the xml file.  The xml file is the datasource for the ListView on the main page.

<root>
<item title="Choose a station"    image="asset:///images/ic_add_entry.png" file="DetailsPage.qml" />
<item title="Social" text="Don't be anti-social" image="asset:///images/ic_add.png"    file="SubDetailsPage.qml" />
<item title="About this App" image="asset:///images/ic_all.png" file="About.qml" />
</root>

 

When the item on the ListView is selected (onTriggered), you can find the items information, which are returned as strings.  Another dynamic option the poster wanted was to set the Page title to the name of the one selected.  The easiest way to do this is to set a Qt variable (Qt.pageTitle), which can be called by the page that is pushed.

var chosenItem = dataModel.data(indexPath);
Qt.pageTitle = chosenItem.title;

From this information, it is simple as setting the source for the blank ComponentDefinition and then doing the push and create.


chosenPage.source = chosenItem.file;
nav.push(chosenPage.createObject());

Of course, the qml Page that is being pushed has to exit in the Asset folder, which goes back to my original point about creating a ComponentDefinition for each Page.  However, in this case, since there are so many Pages for this project, doing this dynamically is probably a better method, since you only need one ComponentDefinition.

The poster also wanted to set the Station Page to have a dynamic list of Stations.  This works exactly the same way, but you don’t need the NavigationPane, since that already exists in the main.qml.

main.qml


import bb.cascades 1.2

NavigationPane {
id: nav

Page {
titleBar: TitleBar {
// Localized text with the dynamic translation and locale updates support
title: qsTr("Welcome") + Retranslate.onLocaleOrLanguageChanged
}
Container {
ListView {
id: mainList
dataModel: XmlDataModel {source: "main.xml"}
listItemComponents: [
ListItemComponent {
type: "item"
StandardListItem {
title: ListItemData.title
description: ListItemData.text
imageSource: ListItemData.image
}
}
]
onTriggered: {
// When an item is selected, we push the recipe Page in the chosenItem file attribute.
var chosenItem = dataModel.data(indexPath);
Qt.pageTitle = chosenItem.title;

// Set the correct file source on the ComponentDefinition, create the Page, and set its title.
chosenPage.source = chosenItem.file;
nav.push(chosenPage.createObject());

}
}
}
}
attachedObjects: [
// Definition of the second Page, used to dynamically create the Page above.
ComponentDefinition {
id: chosenPage
}
]

onPopTransitionEnded: {
// Destroy the popped Page once the back transition has ended.
page.destroy();
}
}

 

About DeanLogic
Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.

About DeanLogic

Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.