Reputation: 10280
I'm currently creating a Twitter client as a way of learning to develop for Blackberry 10. I'm currently trying to create a context menu for a custom ListView item, which on selection will show a dialog in the main layout. However, I cannot get the selected list item to call any functions from the parent Page.
Here is the QML from my custom list item:
import bb.cascades 1.0
Container {
property alias avatar: tracker.imageSource
property alias username: txtTweetUser.text
property alias tweetText: txtTweetContent.text
property alias tweetTime: txtTweetTime.text
signal sendReply(string username)
function cout(text) {
console.debug("[DEBUG] " + text);
}
id: itemTweet
preferredWidth: 768;
preferredHeight: 200
// Actions
contextActions: [
ActionSet {
title: "Action Set"
subtitle: "This is an action set."
actions: [
ActionItem {
title: "Reply"
imageSource: "asset:///reply.png"
onTriggered: {
itemTweet.sendReply(txtTweetUser.text);
}
},
ActionItem {
title: "Retweet"
imageSource: "asset:///retweet.png"
},
ActionItem {
title: "Favourite"
imageSource: "asset:///fav.png"
}
]
} // end of ActionSet
] // end of contextActions list
<Layout for the List Item>...
}
}
And for the main QML file:
import bb.cascades 1.0
TabbedPane {
id: tabbedPane
showTabsOnActionBar: true
Tab {
id: tabTimeline
title: "Timeline"
imageSource: "asset:///twitter-white.png"
Page {
id: pageTimeline
signal openReply
signal showNewTweet
function cout(text) {
console.debug("[DEBUG] " + text);
}
function showTweetWindow(username) {
pageTimeline.dialogNewTweet.text = username;
pageTimeline.dialogNewTweet.visible = true;
}
// Title bar
titleBar: TitleBar {
visibility: Overlay
title: "Twitter"
acceptAction: ActionItem {
id: btnNewTweet
title: "+"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
pageTimeline.cout("action selected");
dialogNewTweet.visible = true;
}
}
}
// Main content
content: Container {
layout: AbsoluteLayout {}
Container {
// Listview for the tweets
ListView {
id: lstTweets
objectName: "lstTweets"
// Components to display the rows
listItemComponents: [
ListItemComponent {
id: listItem
type: "listItem"
TweetItem {
tweetText: ListItemData.content
tweetTime: ListItemData.time
avatar: ListItemData.avatar
username: ListItemData.username
onSendReply: {
cout("Reply selected in parent to " + username);
pageTimeline.showTweetWindow(username);
}
}
}
]
onSelectionChanged: {
}
function itemType(data, indexPath) {
if (indexPath.length == 1) {
return "header";
} else {
return "listItem";
}
}
}
}
DialogNewTweet {
id: dialogNewTweet
visible: false
onShowNewTweet: {
dialogNewTweet.visible = true;
}
}
}
// End container
}
}
... <Other tabs> ...
}
So when the main QML file receives the SendReply signal, it's suppposed to call showTweetWindow(username)
which then makes dialogNewTweet
visible, but instead I get the error ReferenceError: Can't find variable: pageTimeline
. It's definitely a scope issue, but I can't figure out what I'm doing wrong, or if I need to restructure this.
Upvotes: 4
Views: 6413
Reputation: 1532
Answer here:
https://community.blackberry.com/message/182467#182467
What I need to achieve is to operate on a list of data, e.g. delete an item using ContextAction in ListItem in QML, then call a C++ method of an object in QmlDocument's contextProperty. here is how I did it:
C++ code:
QmlDocument *qml = QmlDocument::create("accounts.qml"); root = qml->createRootNode<AbstractPane>(); //Here set the context property, accountsManager was already created qml->setContextProperty("accountsManager", accountsManager); //Set the model for the list view ListView* accountsListView = root->findChild<ListView*>("accountsListView"); accountsListView->setDataModel(accountsManager->getDataModel());
QML code:
Page { content: Container { ListView { id: listView objectName: "accountsListView" listItemComponents: [ ListItemComponent { type: "listItem" StandardListItem{ id: accountItem title: ListItemData.username contextActions: [ ActionSet { deleteAction: DeleteActionItem { title: "Delete" onTriggered: { //it does not work here, "ReferenceError: Can't find variable: accountsManager" accountsManager.doSometing(); } } } ] } } ] function itemType(data, indexPath) { return "listItem"; } } // end of ListView } // end of Container actions: [ ActionItem { title: "Add account" ActionBar.placement: ActionBarPlacement.OnBar onTriggered: { //It works fine here accountsManager.doSomething(); } } ] } // end of Page
And another method:
https://community.blackberry.com/message/453794#453794
At the top Page level add the following line to make the label accessible.
Page { id: topPage onCreationCompleted: { Qt.topLabel = topLabel; }
Then in the button definition you can reference the Qt.topLabel from within the list.
listItemComponents: [ ListItemComponent { type: "item" Button { text: "Change To Three" onClicked: { Qt.topLabel.text = "Three"; } } } ]
Upvotes: 3