Dynamically add item to StackLayout - qt

I have create an item in a file called NetworkSheet. My other QML file (A.qml) contains a StackLayout (id tabStack) and I would like to add NetworkSheet onto the back of the stack.
I'm going in circles due to a couple of incomplete examples. Can someone suggest how to do this? THe closest I got is:
var stackItem = Qt.createQmlObject('import "../tabs"; NetworkSheet{}', tabStack);
tabStack.children.push(stackItem);
but there is no push method for tabStack's children.

There is no need to append/insert the newly created Item onto the StackLayout. By specifying the parent (as the StackLayout) during creation it automatically gets appended onto the end. So just this line is needed:
var stackItem = Qt.createQmlObject('import "../tabs"; NetworkSheet{}', tabStack);

Related

binding to bindable attributes of dynamically generated component/element

I am developing a custom attribute on aurelia to let user select from a list while typing in a textarea. For example, the usage will be something like this:
<textarea value.bind="description" placeholder="your description here" auto-complete></textarea>
and as you probably noticed, the auto-complete is the attribute. Now when I want to show the hints, I want to do this in a custom-element to keep it simple. So the attached method of the attribute will be something like this:
attached() {
this.containerElement = document.createElement('div');
this.containerElement.style.position = 'relative';
const ce = document.createElement('autocomplete-menu');
this.containerElement.appendChild(ce);
const ceView = this.templatingEngine.enhance(ce);
ceView.attached();
const currentParrent = this.element.parentElement;
currentParrent.replaceChild(this.containerElement, this.element);
this.containerElement.appendChild(this.element);
}
now it opens and shows the hint area successfully. The screen-shot:
The problem gets started when I want to communicate to the generated element from the attribute view-model. For example, I want to send a data to its view-model or bind some object to a bindable property of that. For this issue I have found these solutions:
https://discourse.aurelia.io/t/dynamically-add-custom-attribute-to-element/1400/6
https://ilikekillnerds.com/2016/01/enhancing-at-will-using-aurelias-templating-engine-enhance-api/
and also read the last part of this:
https://aurelia.io/docs/binding/how-it-works#abstract-syntax-tree
and figured out that, I have to introduce an object for the element's view-model as its bindingContext or overrideContext. So if I am right, I have tested the solutions below:
this.containerElement.appendChild(ce);
let vm = { test: 1 }
const ceView = this.templatingEngine.enhance({ element: ce, bindingContext: vm });
ceView.addBinding(vm);
ceView.attached();
and
this.containerElement.appendChild(ce);
let vm = { test: 1 }
const ceView = this.templatingEngine.enhance(ce);
ceView.bind(vm);
ceView.attached();
console.log(ceView);
but on the attached lifecycle-hook of the element, I have logged the view-model and noticed that the bindingContext properties are not present on this.
Now there are two questions:
What's the problem with the above solutions and how can I send this kind of data to an enhanced element?
Is there a way to do this with the known method of bindables? I mean defining a bindable property on the element view-model and bind to it after the enhance method is done. Instead of working with bindingContext and overrideContext?
Fortunately the problem has been solved. The solution was not that much complex but 1. it is very very useful for me (as I will describe next) 2. the lack of aurelia documentation made this simple issue hard to solve.
The problem was about I was misunderstanding the meanings of bindingContext and container. I was thinking that bindingContext will refer to view-model of the child element and I must point its container to the parent context (which is the attribute). But I found that I should point the bindingContext to the context of attribute. I still don't know enough about those two meanings but the solution is as simple and beautiful as the following sample:
this.containerElement = document.createElement('div');
this.containerElement.style.position = 'relative';
this.containerElement.style.display = 'flex';
this.containerElement.style.flexDirection = 'row-reverse';
this.ce = document.createElement('autocomplete-menu');
this.ce.setAttribute('filter.bind', 'filter');
this.ce.setAttribute('show.bind', 'showMentionPicker');
this.ce.setAttribute('parent-height', '${element.clientHeight}px');
this.ce.setAttribute('view-model.ref', 'mentionPickerViewModel');
this.ce.setAttribute('on-select.call', 'complete(mentionPickerViewModel.getRemainingOfHint())');
const ceView = this.templatingEngine.enhance({ element: this.ce, container: this.container });
ceView.bind(this);
ceView.attached();
this.containerElement.appendChild(this.ce);
const currentParrent = this.element.parentElement;
currentParrent.replaceChild(this.containerElement, this.element);
this.containerElement.appendChild(this.element);
and the bindings are referring to the attribute's this context which has the following properties:
filter = '';
showMentionPicker = false;
mentionPickerViewModel;
If the sample is not enough for your problem ask me for more information.

Capturing mouseEevents on a container, bypassing its children

I am building an RIA application using Flex 4.6 that contains a main borderContainer (page) that can contain some other borderContainers (graphic or text elements).
I added an event listener on the page to listen to click events:
page.addEventListener(MouseEvent.CLICK, clickHandler, true);
clickHandler looks like this:
private function clickHandler(event:MouseEvent):void
{
// Remove event listeners
page.removeEventListener(MouseEvent.CLICK, clickHandler, true);
// Get click position
objX = event.localX;
objY = event.localY;
}
My problem is that although the event's currentTarget is always the page (normal), the target can either be the page or one of its children, and then localX doesn't give me the position on the page but on the child.
Is there a way to make sure the page is always the target of the event? Something like stopping the capturing phase on the page so it doesn't go deeper?
Thanks in advance for your help
Darrel
I think you may be asking the wrong question. As I understand it, you want the x/y position relative to 'page'. You can use the DisplayObject#globalToLocal() function to find this.
Just take the the global coordinates and convert them to local coordinates relative to 'page':
var coordinates:Point = new Point(event.stageX, event.stageY);
coordinates = page.globalToLocal(coordinates);
objX = coordinates.x;
objY = coordinates.y;

How Do I dispose of a Class Instance in Flex?

I have a menu, each time you click on an item it opens up a screen (a new flex component), when I click back on to the screen I want to dispose of that particular instance, is there an easy way to do this?
UIComponent.removeChild(child) is one way. You can also do this with View States.
The best way to do it is to store all your dynamic instances in an Array, like dynamicHandles:
var dynamicHandles:Array = new Array();
dynamicHandles["test"] = new MCTest();
And then add as children:
addChild(dynamicHandles["test"]);
Finally, whenever you need to remove them, first remove them as child and then clean up the array like so:
removeChild(dynamicHandles["test"]);
dynamicHandles = new Array();

Adobe Flex 3 List Control Selection and Change Event Problem

I created a list control at runtime as following:
var myList:List = new List();
ListArea.addChild(myList);
myList.percentHeight = myList.percentWidth = 100;
myList.itemRenderer = new ClassFactory (components.renderers.myRenderer);
myList.dataProvider = myDataArray;
myList.addEventListener(EVENT.CHANGE, historyBarClickHandler);
//Where myDataArray is an ArrayCollection consisting of my Custom ValueObjects.
When i execute the code it displays my list with custom item renderer, which is fine.
But when bring my mouse over it, it doesn't give any colour highlight which means it is not selecting.
Secondly, when i click on any of the list item, it doesn't dispatch any change event.
I tried a lot but couldn't understand it.
Please Guide
Thanks
Your itemRenderer may be causing another issue, but you're not listening for the correct event. It should be:
myList.addEventListener(ListEvent.CHANGE, historyBarClickHandler);

Flex 3: Embedding MovieClip Symbol to Image Control programmatically

I've reviewed all the documentation and Google results surrounding this and I think I have everything setup correctly. My problem is that the symbol is not appearing in my app. I have a MovieClip symbol that I've embedded to my Flex Component. I need to create a new Image control for each item from my dataProvider and assign this embedded symbol as the Image's source. I thought it was simple but apparently not. Here's a stub of the code:
[Embed(source="../assets/assetLib.swf", symbol="StarMC")]
private var StarClass:Class;
protected function rebuildChildren():void {
iterator.seek( CursorBookmark.FIRST );
while ( !iterator.afterLast ) {
child = new Image();
var asset:MovieClipAsset = new StarClass() as MovieClipAsset;
(child as Image).source = asset;
}
}
I know the child is being created because I can draw a shape and and that appears. Am I doing something wrong? Thank you!
You should be able to simply set child.source to StarClass:
child = new Image();
child.source = StarClass;
See the MovieClipAsset Language Reference for more details:
you rarely need to create MovieClipAsset instances yourself
because image-related properties and
styles can be set to an
image-producing class, and components
will create instances as necessary.
For example, to set the application
background to this animation, you can
simply write the following:
<mx:Application backgroundImage="{backgroundAnimationClass}"/>

Resources