How to access the outer components from listitemcomponents in listview bb10 qml? - qml

I am not able to access the Datasource id from inside of the ListItemComponent. Can anyone help me in regards to this?
ListItemComponent {
type: "item"
Container {
id: listviewcontainer
Container {
preferredWidth: 768
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
CustomImageView {
leftPadding: 10
rightPadding: 10
url: ListItemData.from_image
horizontalAlignment: HorizontalAlignment.Left
verticalAlignment: VerticalAlignment.Center
}
Container {
preferredWidth: 538
layout: StackLayout {
orientation: LayoutOrientation.TopToBottom
}
Container {
layout: StackLayout {
orientation: LayoutOrientation.LeftToRight
}
Label {
text: ListItemData.from
textStyle {
base: SystemDefaults.TextStyles.TitleText
color: Color.create("#2db6ff")
}
}
ImageView {
imageSource: "asset:///Home/img.png"
verticalAlignment: VerticalAlignment.Center
}
}//Container
Label {
text: ListItemData.message
multiline: true
textStyle {
base: SystemDefaults.TextStyles.SubtitleText
}
content {
flags: TextContentFlag.Emoticons
}
}
Label {
id: time
text: ListItemData.time
textStyle {
base: SystemDefaults.TextStyles.SmallText
color: Color.create("#666666")
}
}
}//Container
ImageButton {
id: delete_btn
defaultImageSource: "asset:///Icon/delete.png"
pressedImageSource: "asset:///Icon/delete.png"
verticalAlignment: VerticalAlignment.Center
horizontalAlignment: HorizontalAlignment.Right
onClicked: {
deleteMessage(ListItemData.tid, ListItemData.uid);
}
function deleteMessage(tid, uid) {
var request = new XMLHttpRequest()
request.onreadystatechange = function() {
if (request.readyState == 4) {
var mResponse = request.responseText
mResponse = JSON.parse(mResponse)
var mResponseStatus = mResponse.response[0].receive.status;
var mMsg = mResponse.response[0].receive.message;
if (mResponseStatus == 1) {
msg_DataSource.source = "newurl.com" // This line not works here..
msg_DataSource.load(); // This line not works here..
} else if (mResponseStatus == 0) {
}
}
}// end function
request.open("GET", "myurl.com", true);
request.send();
}// deleteMessage
}//ImageButton
}//Container
}//Container
}//ListItemComponent
Here am not able to work out the following two lines
msg_DataSource.source = "newurl.com"
msg_DataSource.load();
I have tried like below but this also not working
listviewcontainer.ListItem.view.dataModel.message_DataSource.source = "myurl.com";
listviewcontainer.ListItem.view.dataModel.message_DataSource.load();
or this
listviewcontainer.ListItem.view.dataModel.source = "myurl.com";
listviewcontainer.ListItem.view.dataModel.load();

Another simplest way to store the object to global variable using the following code which works fine with me.
onCreationCompleted: {
Qt.tabbedPane = tabbedPane;
Qt.homeTab = homeTab;
}
Here I stored tabbedPane in global variable Qt.tabbedPane on page creation Completed.Now I able to access it from ListItemComponent using Qt.tabbedPane.
Hope it helps.

The simplest way to make the data model accessible would be to declare a property alias to your data model wherever it is defined, for example in your ListView QML file. This would make your data model accessible to the top level component in QML from this property alias. In effect, it gives you a global reference to your data model from anywhere else in QML.
For example, if you data model is called msg_DataSource, then in the QML file where it is defined you can create the property alias like this:
property alias myDataModel: msg_DataSource
Then in your ListItemComponent deleteMessage function, you can use myDataModel like this:
myDataModel.source = "newurl.com"
myDataModel.load();
Note: I am sure you could also do this in a more elegant way using signals and slots, but this way should be quicker and easier to understand.

Related

attach MouseArea to MapParameter

i want to display geojson file on maps and make these shapes clickable to show more details about a building for example.
what i get is just a coordinate ... i need to get geojson object of building clicked
Map {
id: map
anchors.fill: parent
plugin: Plugin {
name: "mapboxgl"
PluginParameter {
name: "mapboxgl.access_token"
value:"sk.eyJ1IjoiYWxub29yLXNjaG9vbCIsImEiOiJjbGF1cmd0YTEwOWNoM3ByNjdxaW0yZXZiIn0.-RGpdTPTSBqrUGc65oLPNQ"
}
MouseArea {
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
onClicked: {
mouse.accepted=true
if (mouse.button == Qt.LeftButton) {
var coord = map.toCoordinate(Qt.point(mouse.x,mouse.y));
console.log(coord.latitude, coord.longitude)
console.log(JSON.stringify(mouse) )
} else {
}
}
}
DynamicParameter {
type: "source"
property var name: "buildingSource"
property var sourceType: "geojson"
property var data: ":building.json"
}
DynamicParameter {
type: "layer"
property var name: "buildinLayer"
property var layerType: "fill"
property var source: "buildingSource"
}
DynamicParameter {
type: "paint"
property var layer: "buildinLayer"
property var fillColor: "#bbb"
}

Application crashing on creating a new object instance of ComponentDefinition Blackberry 10 Native

I am creating a new object instance of a ComponentDefinition using createObject() and then adding it to a container. My application crashes when it reaches the said line of code in QML.
Here is my code:
import bb.cascades 1.0
import Data.UpdateReservationView 1.0 //a custom C++ qmlRegisterType
Page {
property alias resDetails: updateRes.resDetails
attachedObjects: [
ComponentDefinition {
id: enhLabel
Label {
textStyle.fontSize: FontSize.PointValue
textStyle.fontSizeValue: 5.5
textStyle.color: Color.Black
}
},
UpdateReservationView {
id: updateRes
}
]
onResDetailsChanged: {
// some code
var newLabel = enhLabel.createObject(); //the app crashes upon reaching this line
newLabel.text = resDetails[i]["roomName"];
labelsContainer.add(newLabel);
}
ScrollView {
topMargin: 30.0
horizontalAlignment: HorizontalAlignment.Fill
Container{
leftPadding: 20.0
rightPadding: leftPadding
bottomPadding: 50.0
horizontalAlignment: HorizontalAlignment.Fill
Container {
id: labelsContainer
horizontalAlignment: HorizontalAlignment.Left
verticalAlignment: VerticalAlignment.Center
}
}
} //ScrollView ends
} //Page ends
I have tried using .load() instead of .createObject() but get the same result as the ComponentDefinition (enhLabel) is being instantiated elswhere in the code too, and according to my understanding .load() simply loads the control once whereas I require a new instance of it to be created multiple times dynamically.
The queer thing is that the code was running perfectly the day before and I've made no changes in this particular QML file.
What could be the reason for the application to crash. I am sure that it crashes upon reaching the var newLabel = enhLabel.createObject() line by using the old school console.debug() method.
Not sure what has changed on your side but according to the code sample on the BB developer site from what I can see your code looks ok:
Container {
Button {
text: "Click to create bordered text"
onClicked: {
// Creates borderedTextComponent control and appends it
// to the container
var createdControl = borderedTextComponent.createObject();
container.add(createdControl);
createdControl.textString = "Hello Component";
createdControl.padding = 30;
createdControl.textColor = Color.DarkGray;
}
}
Container {
id: container
}
attachedObjects: [
ComponentDefinition {
id: borderedTextComponent
Container {
property variant borderColor: Color.Red
property variant fillColor: Color.White
property variant textColor: Color.Black
property string textString
property real padding: 10;
background: borderColor
leftPadding: padding
rightPadding: padding
topPadding: padding
bottomPadding: padding
Container {
background: fillColor
Label {
text: textString
textStyle.color: textColor
}
}
}
}
]
}
Maybe try this sample to see whether you've got an environmental problem, this one worked for me inside a standard empty Cascades project and paste the code inside the Page{}.
Unfortunately too many things from your code are missing to reproduce the crash on my end.

Accessing ListItemComponents on the run

right now I'm trying to create a ListView which loads the dataModel using a custom QML. Here's the snippet of my code:
ListView {
id: firstPageListView
visible: false
dataModel: firstPageDataModel
layout: GridListLayout {
columnCount: 1
cellAspectRatio: 2.0
headerMode: ListHeaderMode.Standard
verticalCellSpacing: 10
}
listItemComponents: [
ListItemComponent {
//custom qml that will be used
ThumbNote {
title: ListItemData.title
text: ListItemData.text
imageSource: ListItemData.image
listmode: true //list mode
date: ListItemData.date
}
}
]
}
I want to create a button that will change the listmode property of each component into false. By doing so, the object will invoke a function that set in the onListModeChanged() of the ThumbNote QML.
Sorry for my poor english, any help would be appreciated. :)
Perhaps you might consider adding a property to the ListView and binding the ThumbNotes' properties to it.
E.g.:
ListView {
id: firstPageListView
visible: true
dataModel: firstPageDataModel
property bool listMode: true
...
listItemComponents: [
ListItemComponent {
//custom qml that will be used
ThumbNote {
title: ListItemData.title
text: ListItemData.text
imageSource: ListItemData.image
listmode: firstPageListView.listMode
date: ListItemData.date
}
}
]
}
Button {
onClicked: {
firstPageListView.listMode = false;
}
}

Invocation from function in Blackberrry 10 qml?

I have invoked invite to BBM while clicking a button in qml,but i need to send the invitation for the contacts how to do this?my code
Button {
text: "Invite"
onClicked: {
invokeQuery.uri = "pin:210000A"
invokeQuery.updateQuery();
}
attachedObjects: [
Invocation {
id: invokeShare
query: InvokeQuery {
id: invokeQuery
}
onArmed: {
trigger("bb.action.INVITEBBM");
}
}
]
}
Can anyone send me some solutions to solve this.?
Thanks
Invocation query is immutable object which means that values in the query are not dynamic. If you want to update query in dynamic you need to do it via control signals or variables.
For example, you have a component called Inviter with the pin property exposed:
import bb.cascades 1.0
Container {
property string pin
Button {
text: "Invite to BBM"
onClicked: {
query.uri = "pin:" + pin
invoke.trigger("bb.action.INVITEBBM")
}
}
attachedObjects: [
Invocation {
id: invoke
query: InvokeQuery {
id: query
invokeTargetId: "sys.bbm.sharehandler"
onQueryChanged: {
invoke.query.updateQuery()
}
}
}
]
}
Then you can use it this way:
import bb.cascades 1.0
Page {
Container {
layout: DockLayout {
}
TextArea {
id: pinEditor
hintText: "Enter PIN to invite"
onTextChanged: {
inviter.pin = text
}
input.submitKey: SubmitKey.Send
}
Inviter {
id: inviter
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Center
}
}
}
Also, don't forget to enable "Blackberry Messenger" permission in your bar-descriptor.xml and add following libraries to your .pro file:
LIBS += -lbbplatformbbm
LIBS += -lbbsystem

Add a custom button in column header dropdown menus {EXTJS 4}

I want a button in column header dropdown menu of grid in extjs4.
so that i can add or delete columns which are linked in database.
Any help will be appreciated...
Thankyou..:)
Couple of months ago I had the same problem. I've managed to solve it by extending Ext.grid.header.Container (I've overrided getMenuItems method). However, recently, I've found another solution which requires less coding: just add menu item manualy after grid widget is created.
I'll post the second solution here:
Ext.create('Ext.grid.Panel', {
// ...
listeners: {
afterrender: function() {
var menu = this.headerCt.getMenu();
menu.add([{
text: 'Custom Item',
handler: function() {
var columnDataIndex = menu.activeHeader.dataIndex;
alert('custom item for column "'+columnDataIndex+'" was pressed');
}
}]);
}
}
});
Here is demo.​
UPDATE
Here is demo for ExtJs4.1.
From what I have been seeing, you should avoid the afterrender event.
Context:
The application I am building uses a store with a dynamic model. I want my grid to have a customizable model that is fetched from the server (So I can have customizable columns for my customizable grid).
Since the header wasn't available to be modified (since the store gets reloaded and destroys the existing menu that I modified - using the example above). An alternate solution that has the same effect can be executed as such:
Ext.create('Ext.grid.Panel', {
// ...
initComponent: function () {
// renders the header and header menu
this.callParent(arguments);
// now you have access to the header - set an event on the header itself
this.headerCt.on('menucreate', function (cmp, menu, eOpts) {
this.createHeaderMenu(menu);
}, this);
},
createHeaderMenu: function (menu) {
menu.removeAll();
menu.add([
// { custom item here }
// { custom item here }
// { custom item here }
// { custom item here }
]);
}
});
For people who would like to have not just one "standard" column menu but have an individual columnwise like me, may use the following
initComponent: function ()
{
// renders the header and header menu
this.callParent(arguments);
// now you have access to the header - set an event on the header itself
this.headerCt.on('menucreate', function (cmp, menu, eOpts) {
menu.on('beforeshow', this.showHeaderMenu);
}, this);
},
showHeaderMenu: function (menu, eOpts)
{
//define array to store added compoents in
if(this.myAddedComponents === undefined)
{
this.myAddedComponents = new Array();
}
var columnDataIndex = menu.activeHeader.dataIndex,
customMenuComponents = this.myAddedComponents.length;
//remove components if any added
if(customMenuComponents > 0)
{
for(var i = 0; i < customMenuComponents; i++)
{
menu.remove(this.myAddedComponents[i][0].getItemId());
}
this.myAddedComponents.splice(0, customMenuComponents);
}
//add components by column index
switch(columnDataIndex)
{
case 'xyz': this.myAddedComponents.push(menu.add([{
text: 'Custom Item'}]));
break;
}
}
I took #nobbler's answer an created a plugin for this:
Ext.define('Ext.grid.CustomGridColumnMenu', {
extend: 'Ext.AbstractPlugin',
init: function (component) {
var me = this;
me.customMenuItemsCache = [];
component.headerCt.on('menucreate', function (cmp, menu) {
menu.on('beforeshow', me.showHeaderMenu, me);
}, me);
},
showHeaderMenu: function (menu) {
var me = this;
me.removeCustomMenuItems(menu);
me.addCustomMenuitems(menu);
},
removeCustomMenuItems: function (menu) {
var me = this,
menuItem;
while (menuItem = me.customMenuItemsCache.pop()) {
menu.remove(menuItem.getItemId(), false);
}
},
addCustomMenuitems: function (menu) {
var me = this,
renderedItems;
var menuItems = menu.activeHeader.customMenu || [];
if (menuItems.length > 0) {
if (menu.activeHeader.renderedCustomMenuItems === undefined) {
renderedItems = menu.add(menuItems);
menu.activeHeader.renderedCustomMenuItems = renderedItems;
} else {
renderedItems = menu.activeHeader.renderedCustomMenuItems;
menu.add(renderedItems);
}
Ext.each(renderedItems, function (renderedMenuItem) {
me.customMenuItemsCache.push(renderedMenuItem);
});
}
}
});
This is the way you use it (customMenu in the column config let you define your menu):
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
plugins: ['Ext.grid.CustomGridColumnMenu'],
columns: [
{
dataIndex: 'name',
customMenu: [
{
text: 'My menu item',
menu: [
{
text: 'My submenu item'
}
]
}
]
}
]
});
The way this plugin works also solves an issue, that the other implementations ran into. Since the custom menu items are created only once for each column (caching of the already rendered version) it will not forget if it was checked before or not.