In flex4 & as3 how do you change the button label dynamically? - actionscript-3

Is there any way to change Spark button label dynamically? When i click on it, i want the label to change. I bind the String to label and gives value for the first time, but even flashBuilder shows me that Data binding will not be able to detect assignments.
Here is my button:
<s:Button name="button" label="{butt}" x="5" y="3" useHandCursor="true"
click="start()" buttonMode="true" cornerRadius="5"
skinClass="skins.CustomButtom"/>
And here is assigment:
public var butt:String = "Start";
Update
Both answers work.

Make the variable Bindable like this:
[Bindable]
public var butt:String = "Start";

It is not advisable to have buttons with changing labels.
Even if you must, it is preferable to change the label property directly instead of introducing a binding because Flash Player needs to instantiate extra listeners for bound variables.
In this case, a binding is required only if you are going to be changing the label frequently.
Without the bindable, you might have noticed that Flash will assign the value "Start" to the label of the button (generally, the value of the bound variable at the time of creation of the button).

Related

Flex/Spark: How much logic in view? How to clear a TextField as a reaction to a user click or an event?

When using Flex with Spark, I have a simple chat window with a TextInput to enter your message and a send Button.
TextInput
Starts out as ""
Should be set to "" last in the function that handles the message sending
Should also be set to "" as a response for event="myOtherEvent"
Button
Should only be enabled when the TextInput's text.length > 0
At first I thought it was pretty clean to skip binding the text being entered into the TextInput to anything in my model and let that logic for button enabling/disabling stay in the view.
I still feel that it's a pretty nice approach except for the fact that it isn't a complete solution as it does not clear the TextInput.text as a response to receiving event="myOtherEvent".
The MXML for that partial solutions is:
<s:TextInput id="chatText" width="100%" height="32" />
<s:Button
label="Send"
enabled="{chatText.text.length > 0}"
click='{model.send(chatText.text); chatText.text=""}'
/>
If it wasn't for my event response requirement, how do you feel about that solution?
There is some logic in the Button, but just basic setting and checking. I know that it's a good idea to separate logic and presentation, but I thought this was a nice balance.
A complete solution I can think of would be to:
Have a two way binding of chatText.text and a property in my model
And in the set method for that property, I would dispatchEvent(new Event("updateButton")
A function in the same model class would bind to that event. That function would also be read in enabled="{model.thatFunction()}" of the Button. The function would return chatTextStringPropertyInModel.length > 0 and thus (by jumping through some hoops) would see to that the send-Button is enabled when there is text available for sending.
The model.send(chatText.text) can set chatTextStringPropertyInModel="" after sending and as that property is two-way bound with chatText.text the change would be reflected in the UI too.
My questions:
How much logic is all right to have in the view?
How should I solve this? What is most elegant and maintainable?
Maybe I'm confused but I don't see an issue in your solution. You just need to add an event handler for your other event
<fx:Script>
<![CDATA[
//clear text and disable button on other event
private function onMyOtherEvent(event:Event):void
{
chatText.text = "";
}
]]>
</fx:Script>
<s:TextInput id="chatText" width="100%" height="32" />
<s:Button
label="Send"
enabled="{chatText.text.length > 0}"
click='{model.send(chatText.text); chatText.text=""}'/>
Also I don't think there's anything wrong with a view component handling it's own view logic...

How can you make a Datagrid's Image-based itemRenderer either visible or not, depending on the value of its row and column in the datagrid?

The description is basically the same as the title. This is a related post I made a little while ago: Why would an Image-based itemRenderer always be visible? Basically the dataField that's being used for the itemRenderer's column in this case is "ongoing", and I want to set the itemRenderer and/or its image to true or false, depending on the value of ongoing in that row. If the itemRenderer is Label-based, I'm able to set the text to different values, depending on that. Certain specific properties, like visible, are problematic though. Documentation I've found so far on using states is very difficult to follow, and I'm not even sure those apply here. How do I do this? The current code, by the way is as follows:
<mx:DataGridColumn dataField="ongoing" id="ongoing" headerText="">
<mx:itemRenderer>
<mx:Component>
<mx:Image source="logo.jpg">
<mx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
super.visible = (value.ongoing != 'False');
}
]]>
</mx:Script>
</mx:Image>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
I've also tried working with the set visible override. Thanks!
That doesn't make any sense, especially in a Datagrid. If you don't want to display data, filter for it using a collection's filter function. Otherwise you're having empty cells.
Also, you're working against the component live cycle:
Setting visible in data will be called before the component is actually rendered - so there is no effect. If you're using vanilla objects and no classes, changes of the property's value will not have any effects as well.
On a site note: Boolean should be Booleans, no Strings and inline renderers can lead to some scoping issues, that's why i'd recommend using a separate component definition (aka .as or .mxml file).
The answer can loosely be found here by gokiさん:
http://www.fxug.net/modules/xhnewbb/viewtopic.php?topic_id=2229
At the moment at least, I'm having to actually set the source to either the image or a blank string to get this to work (looked like he was trying to do something slightly different), but it works.
EDIT: These two lines of code replaced where he was messing with the visible property:
var property0:SetProperty = new SetProperty(this, "source", "");
var property1:SetProperty = new SetProperty(this, "source", "dot.png");

Flex How to change button state in actionscript?

i can do this:
<s:Button id="Btn" enabled.State1="false" />
But the following code is giving me an error.
private function enableDisable():void{
Btn.enabled.State1="false"; //Error: Access of undefined property State1
}
how to code enabled.State1 in ActionScript?
Thanks
I know this is not what you want to hear, but here it goes anyway: why do you want to do that? The whole purpose of the states is that you wouldn't have to write tons of ActionScript to do the same thing.
Why you can't do it like that
By writing Btn.enabled.State1 in ActionScript you're essentially saying: give me the property called 'State1' of the Boolean instance called 'enabled'. Obviously that won't work because a Boolean doesn't have such a property. You're confusing the MXML dot (.) notation - used for assigning values to properties based on states - with the ActionScript dot notation - used for reading/writing properties.
A solution or as close as it gets
Since it's the very nature of this feature that you would use it in MXML, you can't do exactly what you're asking for in ActionScript. The next best thing would be to listen for StateChangeEvent en set the Button's 'enabled' property according to the new state name.
addEventListener(StateChangeEvent.CURRENT_STATE_CHANGE, onStateChange);
private function onStateChange(event:StateChangeEvent):void {
switch (event.newState) {
case "wrong": Btn.enabled = false; break;
case "correct": Btn.enabled = true; break;
}
}
(I'm using the same states as in James' answer)
I think you may be using states in the wrong context. For instance, you have component which contains a user input with a button next to it. The button is only enabled when the correct word is input. You would define two states for the component, perhaps correct and wrong.
<s:states>
<s:State name="wrong" />
<s:State name="correct" />
<s:states>
You would then, similar to what you've done above, set individual properties for the buttons depending on the state:
<s:Button id="Btn" enabled.wrong="false" enabled.correct="true" />
By default, the state of the component would be wrong. After handling user input and checking if the correct word is entered, the state of the component would be changed to correct.
Normally the state-specific properties of components are set at compile time and the state of the component itself changed at runtime.
Here is an overview of states in Flex 4.6

Change image dynamically in Flash Builder 4.6

In my code I have defined the following:
<s:Image id="test" x="50" y="50" width="30" height="30" click="onClick_clickHandler(event)" smooth="true" smoothingQuality="high" source="#Embed('icons/myImage_60_off.png')"/>
What I want is to be able to change the source of the image every time the user clicks on the image - similar to the way favourites work on a browser.
I have no idea how to change the source of the image from my code.
Thank you
I had a hidden datagrid with my solution, because it started off with a visible one.
The image looked like this:
<mx:Image top="153" left="10" right="10" bottom="5" source="{dgpick.selectedItem.ImageFile}" />
Every time someone clicks on the image, I would increase the selected index of the datagrid, and the labels will display the corresponding data, as they are also bound to its data.
The image can also have a link to an XML file that you can load like this:
<s:HTTPService id="Config"
url="config.xml"
result="resultHandler(event)"/>
private function resultHandler(event:ResultEvent):void
{
ImagesURL = event.result.images.ImagesURL[iCounter];
}
Every time someone clicks on the image, you can increase the counter, and so forth.
Hope this gives you some ideas.
There are 20 ways to do this.
If you need more code, add a comment, with what you need.
I finally did it!
public var image_loader:Loader; // define a new loader
image_loader = new Loader(); // create the new loader at the desired location (in my case in the initialization method of the page
image_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded); //add a listener and a function to assign to the listener
depending on where the command has to be executed
image_loader.load(new URLRequest('location of the image')); //this will load the image dynamically
function imageLoaded(event:Event):void {image_Id.source = image_loader;} //where image_Id is the id of the s:Image tag to be modified
also, I had to remove the source from the s:Image tag previously posted
The rest is just logic of the way the application needs to implement the functionality, so it's pretty much left to the developer's desires

Three way binding in MXML custom component (using only mxml)

I'm trying to do this using only mxml, no <script> tags, although I don't necessarily need a solution that's only mxml. It was more of an educational exercise to see if I could do it all in mxml.
I have a custom component that has a slider and textinput and their value/text properties are bound together. I'm surfacing a few properties of the slider in my component so that it can sort of be treated like a slider.
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" verticalAlign="middle" horizontalGap="0">
<mx:int id="value">{slider.value}</mx:int>
<mx:int id="minimum">0</mx:int>
<mx:int id="maximum">100</mx:int>
<mx:int id="tickInterval">25</mx:int>
<mx:Array id="labels">['0%','50%','100%']</mx:Array>
<mx:HSlider id="slider" liveDragging="true" snapInterval="1"
value="{int(input.text)}"
minimum="{minimum}"
maximum="{maximum}"
tickInterval="{tickInterval}"
labels="{labels}"/>
<mx:Spacer width="25"/>
<mx:TextInput id="input" restrict="0-9" text="{slider.value}" maxChars="3" width="30"/>
<mx:Label text="%"/>
</mx:HBox>
Notice the slider's VALUE property is bound to the input field's TEXT property, and vice versa. A two-way binding. This lets the user slide the thumb or type in the input field to select a value and they stay in sync with each other.
Also, the component's VALUE property is bound to the slider's VALUE property so that the value of this component will always contain the value of the slider (so that the component can be used like a slider).
The slider's properties are also bound to the component's properties (min, max, tick marks)
The problem is that I want to initialize the value of the slider from the value of the component, but the slider's value is already bound to the textinput. Can I also bind it to the component?
My application will have something like this:
<local:mycomponent minimum="20" maximum="80" labels="['20','50','80']" value="40"/>
A few things I tried that didn't work:
(1) I had an initialize handler.
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" initialize="slider.value=value">
This worked if my app had
myslider.value = 40;
but didn't work if I had
<local:mycomponent value="40"/>
(2) I tried a creationComplete handler
(3) I tried mx:binding
<mx:Binding source="slider.value" destination="this.value"/>
It seems like I'm missing something simple.
Note the curly brackets:
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" initialize="{slider.value=value}">
In the brackets, there may be any code. Without them, there can only be event handler (function).