How to replace one mxml instance with another? - apache-flex

I am pretty new to Flex.
What I am trying to achieve is to have two different layouts and initialize them based on the user's choice. Each of these layouts is defined in its own mxml component.
I have two components:
and
I could add both in the beginning and have only one visible but I don't want to go down that road. What I tried so far is to have an event handler that replaces the current instance but I hit a wall. Let's say that LeftAligned is the component initialized first and then I want to change it with RightAligned. Now:
If I try to replace the lement based on its id: newElement:RightAligned = new RightAligned(); LayoutArea = newElement; I get a implicit coercion error that it can't convert RightAligned to LeftAligned.
If I try to removeElement(LayoutArea); addElement(newElement); then I get an exception thrown from other parts of the application that call LayoutArea's methods (event based).
What solutions are there for this? Thank you

Related

How to initialise controllers using provider state in flutter

I recently refactored half my app to use the provider pattern and i now have a problem. The main issue is that i need to initialise controllers in the init (e.g. a text controller to have an initial value or the list size of a tab controller)
How am i meant to init Controllers if the data i need has to come from the state in the build method.
For example.
// This must go in the build as it requires state
myTabsController = TabController(length: myState.list.length, vsync: this);
I'm initialisng the controller every time it builds now... How am i meant to put this in the init but still access the state variables (as there is no context).
I've tried using the afterFirstLayout() callback from the AfterLayoutMixin library but that just causes more problems. Currently with the tab bar it flashes error as no tab initialised for the first frame and then displays properly when the afterFirstLayout is called and initialises the tab. This seems like a hacky fix
I would like to learn more about how to use this pattern properly and what would be the best solution to this problem.
Feel free to ask me to clarify more.
Thanks for your help.

How to assign Custom Activity Result to a Root level variable at Runtime (in Custom Activity Execute method) in workflow?

Assume that I have a workflow with 3 Custom Activities which are placed in a Sequence Activity. And I created a Boolean variable (name it as “FinalResult”) at Sequence Activity level (Root) to hold the Result. My Intention is, I want to assign each Custom Activity Result to Root level variable (“FinalResult”) within the Custom Activity Execute method after finishing the activity.
I can get this by declaring the output argument in Custom Activity and placing the variable name at design time in the properties window of activity manually while designing the policy.
But I don’t want to do this by the end user. I want just the end user drag and drop the activities and write conditions on the” FinalResult” variable. Internally I have to maintain the Activity Result in “FinalResult” Variable through programmatically.
Finally I want to maintain the workflow state in “FinalResult” variable and access it anytime and anywhere in the workflow.
I tried like this below getting error "Property does not exist".
WorkflowDataContext dataContext = context.DataContext;
PropertyDescriptorCollection propertyDescriptorCollection = dataContext.GetProperties();
foreach (PropertyDescriptor propertyDesc in propertyDescriptorCollection)
{
if (propertyDesc.Name == "FinalResult")
{
object data = propertyDesc.GetValue(dataContext);// as WorkUnitSchema;
propertyDesc.SetValue(dataContext, "anil");
break;
}
}
Please let us know the possible solutions for the same.
I do this all the time.
Simply implement IActivityTemplateFactory in your activity. When dragged and dropped onto the design surface, the designer will determine if your activity (or whatever is being dropped) implements this interface. If it does, it will construct an instance and call the Create method.
Within this method you can 1) instantiate your Activity and 2) configure it. Part of configuring it is binding your Activities' properties to other Activities' arguments and/or variables within the workflow.
There are a few ways to do this. Most simply, require these arguments/variables have well known names. In this case, you can simply bind to them via
return new MyActivity
{
MyInArgument = new VisualBasicValue<object>(MyActivity.MyInArgumentDefaultName),
};
where MyActivity.MyInArgumentDefaultName is the name of the argument or variable you are binding to.
Alternatively, if that variable/argument is named by the user... you're in for a world of hurt. Essentially, you have to
Cast the DependencyObject target passed to the Create method to an ActivityDesigner
Get the ModelItem from that AD
Walk up the ModelItem tree until you find the argument/value of the proper type
Use its name to create your VisualBasicValue
Walking up the ModelItem tree is super duper hard. Its kind of like reflecting up an object graph, but worse. You can expect, if you must do this, that you'll have to fully learn how the ModelItem works, and do lots of debugging (write everything down--hell, video it) in order to see how you must travel up the graph, what types you encounter along the way, and how to get their "names" (hint--it often isn't the Name property on the ModelItem!). I've had to develop a lot of custom code to walk the ModelItem tree looking for args/vars in order to implement a drag-drop-forget user experience. Its not fun, and its not perfect. And I can't release that code, sorry.

Flex 3: getting .length of custom component id within a repeater... works sometimes, but not all the time

I have a repeater that populates a component, called 'project'. The project components are given an ID of 'wholeProject'. In all of my functions up until now, I was able to determine how many project components were made by doing the following:
wholeProject.length;
I used this in for loops, for each loops, and for changing the item settings within a project, i.e. something like this:
wholeProject[i].studentName = "Billy Bob";
However, I'm creating a new function that does not seem to like this wholeProject.length reference. I'm using it within the same level as all the others (i.e. the parent level). So far, my function is simply this:
public function getStudentYears():void
{
Alert.show(String(wholeProject.length));
}
when the application loads, the alert message simply does not appear. If I change the alert to something like this:
Alert.show("This is just a test.");
it works just fine. But for some reason, the wholeProject.length doesn't work in this function whereas it does in all my other ones. Anybody have any ideas as to why this is happening?
Use your repeater's data provider length instead.

Flex: select tree node right after the dataProvider is been assigned / updated / replace

i have a Flex tree control and im trying to select a tree node 3 levels down right after the dataProvider is assigned with a collection object like the following.
basically treeItem1, treeItem2, treeItem3 are the nodes in the tree and treeitem3 is a child of treeItem2 which is a child of treeItem1. Assume these treeItem(1,2,3) are referenced correctly from the collection items.
my problem is that if i wait for the whole component to load completely then select the nodes, it open/select/scrolltoIndex correctly. However, if i were to select the node right after the dataProvider is assigned, then it doesn't even open or select (basically the this.treeService.selectedItem is always null).
can anyone point out what i did wrong? is there anything needs to happen after the dataProvider is assigned?
thanks
this.treeService.dataProvider = oPricingHelper.getCurrentPricingSercicesTreeSource();
this.treeService.expandItem(treeItem1, true);
this.treeService.expandItem(treeItem2, true);
this.treeService.selectedItem = treeItem3;
this.treeService.scrollToIndex(this.treeService.selectedIndex);
I have used the updateComplete event to know when a component (such as a DataGroup or List) has completed rendering after performing a simple task (such as updating the dataProvider reference). Of course, you have to be careful and remove listening to updateComplete because it can run a lot, unless you have a need for it to run.
Something like:
//...some function...
this.treeService.addEventListener(FlexEvent.UPDATE_COMPLETE, onTreeUpdateComplete);
this.treeService.dataProvider = oPricingHelper.getCurrentPricingSercicesTreeSource();
//...rest of some function...
private function onTreeUpdateComplete(event:FlexEvent):void {
this.treeService.removeEventListener(FlexEvent.UPDATE_COMPLETE, onTreeUpdateComplete);
this.treeService.expandItem(treeItem1, true);
this.treeService.expandItem(treeItem2, true);
this.treeService.selectedItem = treeItem3;
this.treeService.scrollToIndex(this.treeService.selectedIndex);
}
I'm not positive your experiencing the same issue but I seem to have the same type of problem with using the advanced data grid, it appears in these cases where the dataprovider is acceptable as multiple types, the components do some extra work in the background to wrap things up into something Hierarchical (HierarchicalData or HierarchicalCollectionView) and in doing so the dataprovider setter call is not synchronous (so it will return before actually having assigned the internal property storing the dataprovider). I've used callLater in this case with moderate success, callLater is generally a bad practice but basically adds a function to a list of functions to call once background processing is done, so this is assuming that something in the dataprovider setter called UIComponent.suspendBackgroundProcessing() and that it will subsequently call UIComponent.resumeBackgroundProcessing() and then it will execute the list of functions added by using callLater. Alternatively you could use setTimeout(someFunction,1000).
These are both "hacks" the real solution is to dig into the framework code and see what it's really doing when you tell it to set the dataprovider. Wherever you see that it actually has set the dataprovider you could extend that class and dispatch an event that you could listen for to run the function to do the selections after this point.
If anyone has a better solution please by all means correct me (I would love to have a better answer than this)

Flex - Why is my custom event not being registered with the following event listener?

printableInvoice.addEventListener(batchGenerated, printableInvoice_batchGeneratedHandler);
Results in this error:
1120: Access of undefined property batchGenerated. I have tried it as FlexEvent.batchGenerated and FlashEvent.batchGenerated.
The MetaData and function that dispatches the even in the component printableInvoice is all right. It I instantiate printableInvoice as an mxml component instead of via action-script it well let put a tag into the mxml line: batchGenerated="someFunction()"
Thanks.
batchGenerated should be a string.
It looks like your application dispatches an event whenever the batch is generated.
I'm assuming inside your code you have something along the lines of either:
dispatchEvent( new BatchEvent("batchGenerated") );
or
dispatchEvent( new BatchEvent(BatchEvent.BATCH_GENERATED) );
The second way is usually preferred as using variables instead of magic strings gives you an extra level of compile time checking.
The first required parameter of events is typically the type of the event - Event.CHANGE (aka "change"), FlexEvent.VALUE_COMMIT (aka "valueCommit") etc.
This is what the event listener is actually comparing against.
So in your event listener code above, you would want to change the line to be either:
printableInvoice.addEventListener("batchGenerated", printableInvoice_batchGeneratedHandler);
or hopefully
printableInvoice.addEventListener(BatchEvent.BATCH_GENERATED, printableInvoice_batchGeneratedHandler);
If you want to go further, the Flex documentation goes into some detail as to how the event system works, and how the events are effectively targeted and handled through the use of the Capture, Target, and Bubble phases.

Resources