Set Property of a Control on a Different State? - Flex 4 - apache-flex

I'm having trouble setting the property of a control on another state.
Latest_News_Display is under the Latest_News state. I want to set Latest_News_Display's x property even if the currentState is set to Intro. However, when I try to use Latest_News.Latest_News_Display.x = 10,it returns an error that says 1120: Access of undefined property Latest_News. So how do I go about doing it?

There is no guarantee a component in another state has been created at the time you are trying to set it. It's hard to say for sure without seeing your code, but I'm guessing that is the issue based on your error.
You'll, basically, have to create your own method of deferred value setting. So, when you try to set it do something like this:
if(Latest_News_Display){
Latest_News_Display.x = 10
} else {
cachedLatest_News_DisplayX = 10
}
Then listen to the currentStateChange event and set the new value then:
protected function onCurrentStateChange(event:StateChangeEvent):void{
Latest_News_Display.x = cachedLatest_News_DisplayX
}
I'll also add that, based on the bolded items in your question that it appears you are trying to access a state by name Latest_News. If you create a local variable pointed at a specific state, you can do this. But, if you're using MXML then you probably didn't. Even so, a state is just, basically, an array of overrides you wouldn't be able to access components in that state directly.

Related

VS windows forms

I was just wondering is there a less bloating and simpler way of clearing input elements say made up of text boxes, check boxes and combo boxes to a empty state, that being removing text from them etc. I have like maybe 50+ and was hoping of a tidier way of doing this.
Another scenario I have is a set of 18+ elements, each set having 2 text boxes and 2 check boxes, one being an 'enabled' check box that when selected will enable/disable its set. Would there be a way of creating a method to handle this and make the required changes rather than having to type out the same thing happening for each set?
if (cbEnhancedInputOptionEnabled1.Checked == true)
{
tbEnhancedInputOptionText1.Enabled = true;
tbEnhancedInputOptionInputID1.Enabled = true;
cbEnhancedInputOptionDefaultState1.Enabled = true;
}
else
{
tbEnhancedInputOptionText1.Enabled = false;
tbEnhancedInputOptionInputID1.Enabled = false;
cbEnhancedInputOptionDefaultState1.Enabled = false;
}
so I would have 18 of these just changing based on the number which correlates to the set. Each one being in their own cbEnhancedOptionEnabled_CheckedChanged event.
Is there a way of passing controls by reference to a method? that'll do the same as above but to the controls passed?
For the first scenario, you can create a method named, for example, ResetAllControls, where you can set the status of each control to its default state.
For the second scenario, you may implement CheckedChanged event for each checkbox to control what to be enabled/disabled.
Another option is to give prefixed name for each control in each set. For example, set1_txtBox, set2_ddl, etc. Then define a common method. The method should accept a parameter (based on the prefix or set order number) to decide which set that you want to enable/disable. In that method, you can loop through the list of controls of the Form and, based on the parameter, and enable/disable which controls that you wish. Finally, you can implement the CheckedChanged event for each checkbox that is responsible for enabling/disabling each set's status. In each CheckedChanged method, you call the common method and pass your parameter.
Let me know if these help you.

Update shiny input from java script

I've looked around and tried a few things but I can't seem to get it to work. I want to be able to update the value stored in input$someVar from a bit of js code. What I need to on a certain element click, I need to update the input$someVar value. I know there are functions like "updateSelectInput()" but those are called from the server.
I can physically change the value of the data in the HTML that is used int he data attribute and that is displayed, but the server doesnt see this as a change and the input$someVar stays the same.
I have tried
var selectBind = Shiny.inputBindings.bindings[5];
selectBind.binding.setValue('#loc', newValue);
within an event handler, where #loc is the id of the input element, in hope that I could do it that way but this gives me an error.
Is there a way to do the functionality of "updateSelectInput()" within java script in the ui?
Yes, there is a way. Use the JavaScript function Shiny.onInputChange.
// change the value of an input
document.getElementById("id").value = "value";
// report the change to shiny
Shiny.onInputChange("id", "value");

flex how to refresh already created view

How can I refresh view after a certain event?
I have a view which contains multiple groups. I want to show or hide some groups.
onCreationComplete() or initialize() method works only at the beginning of the view creation.
Try invalidateDisplayList() on the view
Let me know if that doesn't do the trick and we'll try some other tricks.
I personally don't like the answer that says to call invalidateDisplayList (sorry no offense Nate nothing personal). I feel it's too vague and doesn't explain what this does under the hood and furthermore you shouldn't have to call it directly in cases such as the one explained in the OPs question. You can simply create booleans that are bindable for each of the groups you'd like to show/hide then in the event handler set those booleans to the appropriate value and if they are bound to the visible and include in layout properties of the containers those containers will internally call invalidateDisplayList after calling set visible and consequently commitProperties.
This is basically what happens under the hood as I understand it: The way this works is values aren't committed or used to update the display until the next frame this way it doesn't get bogged down doing unnecessary layout calculations. So you update the bindable property which fires an event which triggers a notification in the listener (in this case a function that sets the property on your control), that in turn passes along the value to the control which sets an internal flag to update the property and calls invalidateProperties. When it hits the next frame redraw it sees that the properties flag is dirty (true) and then calls commitProperties, this computes/sets the appropriate values (possibly also invalidating then "fixing" the size using invalidateSize() and measure()) and calls invalidateDisplayList, then during the same frame it sees that the display list flag is dirty so it calls updateDisplayList, here it uses the values of the properties to draw appropriately.
You should also be able to achieve this using states, which add or remove children from the display list based on an array of "actions" for each state.

list.dataGroup.getElementAt() not returning all the elements

I'm trying to cycle through my list itemRenderers to change the data of a particular item. The code runs well until the for index becomes 7 (which is the maximum number of visible elements on my list). When the index is 7 or more, the getElementAt() function returns null. What could possibly be the problem?
var itemRenderer:ItemRenderer;
var numItems:int = list.dataGroup.numElements;
trace(numElements) // outputs 14
for(var i:int = 0; i < numItems; i++){
itemRenderer = list.dataGroup.getElementAt(i) as ItemRenderer;
if (itemRenderer.data.name == "bar") {
itemRenderer.data.option = "foo";
break;
}
}
If you want to change the data of a particular item, why not change it from the data you gave to the dataProvider? Changing it directly in the item renderer is ludicrous.
And for future reference, the reason why that fails is because of something called virtualization. Essentially, not all item renderers are created, only the ones visible.
Spark List uses virtual layout by default (useVirtualLayout = true). It allows to reuse item renderers and increase performance and decrease resources usage. In your case you can set useVirtualLayout=false for your List.
But it is very possible you do something wrong if you need to list List's item renderers from outside. Try to solve your problem some other way and remain using virtual layout.
You can also use the RendererExistenceEvent which is fired when the ItemRenderer of the DataGroup when it receives data and is rendered. Listen for the event rendererAdd on the DataGroup.
<s:DataGroup id="dataGroupList" dataProvider="{_listData}"
width="100%" height="100%"
rendererAdd="list_rendererAddHandler(event)"/>
For more information, check out the help document for RendererExistenceEvent.
Though some say it's not best practices for accessing and changing data in the ItemRenderer directly, there may be other use cases where you need to just that. For instance, if you want to toggle the selected or enabled properties of the list based on some user interaction or state change. Best practices only apply on the simplest use cases, other use cases require you to use these events or modify the control itself.

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)

Resources