Question

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.

Was it helpful?

Solution

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";
                    }                        
                }
            }
        ]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top