how do I get a handle to a custom component in Flex? - apache-flex

I have a custom login component in Flex that is a simple form that dispatches a custom LoginEvent when a user click the login button:
<?xml version="1.0" encoding="utf-8"?>
<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" defaultButton="{btnLogin}">
<mx:Metadata>
[Event(name="login",tpye="events.LoginEvent")]
</mx:Metadata>
<mx:Script>
import events.LoginEvent;
private function _loginEventTrigger():void {
var t:LoginEvent = new LoginEvent(
LoginEvent.LOGIN,
txtUsername.text,
txtPassword.text);
dispatchEvent(t);
}
</mx:Script>
<mx:FormItem label="username:">
<mx:TextInput id="txtUsername" color="black" />
</mx:FormItem>
<mx:FormItem label="password:">
<mx:TextInput id="txtPassword" displayAsPassword="true" />
</mx:FormItem>
<mx:FormItem>
<mx:Button id="btnLogin"
label="login"
cornerRadius="0"
click="_loginEventTrigger()" />
</mx:FormItem>
</mx:Form>
I then have a main.mxml file that contains the flex application, I add my component to the application without any problem:
<custom:login_form id="cLogin" />
I then try to wire up my event in actionscript:
import events.LoginEvent;
cLogin.addEventListener(LoginEvent.LOGIN,_handler);
private function _handler(event:LoginEvent):void {
mx.controls.Alert.show("logging in...");
}
Everything looks good to me, but when I compile I get an "error of undefined property cLogin...clearly I have my control with the id "cLogin" but I can't seem to get a"handle to it"...what am I doing wrong?
Thanks.

ah! I figured it out...it was a big oversight on mine...it's just one of those days...
I couldn't get the handle on my component because it was not yet created...I fixed this by simply waiting for the component's creationComplete event to fire and then add the event listener.

You can also do something like this I believe:
<custom:login_form id='cLogin' login='_handler' />

You can also do something like this I
believe:
<custom:login_form id='cLogin' login='_handler' />
Minor clarification as there seem to be some confusion in the original code.
Indeed and the reason for this is that a metadata tag has been used to declare the event that is to be made available that way.
<mx:Metadata>
[Event(name="login", type="events.LoginEvent")]
</mx:Metadata>
However, there was no need to add the event metadata when instead of a component "event" property (login='_handler') an event listener was used:
cLogin.addEventListener(LoginEvent.LOGIN,_handler);
addEventListener -> no metadata tag needed
event property in the component tag -> metadata tag required

Related

Flex: Read values from Repeater

I am using a simple Repeater which has a single component(TextInput).
<mx:Repeater id="myrep" dataProvider="{myAC}" >
<local:TextInputRepeater id="tiRepeater" displaytext="{myrep.currentItem}" />
</mx:Repeater>
<mx:Button label="Get Data" click="getNewValues(event)" />
The repeater has following code:
[Bindable]
public var displaytext:String = "";
<mx:TextInput id="repeatText" text="{displaytext}" change="repeatText_changeHandler(event)"/>
Here is what I want : on click of button in getNewValues function, I want to read the values (user might possibly have changed in the textInputs).
Well, it was a silly issue which I overlooked.
Solution is, tiRepeater[index] will give you the udpated repeater object.

Flex 4.6 with itemrenderer with textinput inside

i have a itemrenderer that is contain:
<s:TextInput x="10" y="41" width="60" name="txtprice"/>
and i want to access to this field from outside.
how can i do this?
You can do something like this:
<s:List id="list" itemRenderer="com.myDomain.myProject.MyRenderer" />
<s:Button label="click me" click="onButtonClick()"/>
<fx:Script>
<![CDATA[
import mx.core.IVisualElement;
protected function button1_clickHandler(event:MouseEvent):void
{
var myRenderer:CustomItemRenderer = list.dataGroup.getElementAt(0) as CustomItemRenderer;
}
]]>
</fx:Script>
Since itemRenderers are usually recycled, an itemRenderer is not created for an element that is off screen. That is, if your list has 20 elements, and only the first 10 are visible, getElementAt() will return null if you try to get the 11th-20th elements. If you scroll the element into view, the renderer is created/recycled, and then you can retrieve it.
I seem to recall a better way of dealing with this, but it's not coming to mind.
Note there is another method: list.dataGroup.getVirtualElementAt() but this seems to behave the same for me as the non-virtual method.
Finally, be sure to assign the TextInput in your renderer an idso you can reference it after you retrieve the renderer:
<s:TextInput id="txtprice" />

Add button to the flex accordion header which can clickable

I want to add a button with a cross to the header of the accordion which can be clickable. that means i want to display a message when the some one click on that button. i go through many of the samples in the web but couldn't get it done. if any one who knows do this in flex4 it will very helpful.
I tried with also a CanvasButtonAccordionHeader, it shows the button but when i click it, it didn't give the message although i created the click event handler.
if somebody know how to resolve this please describe it with a simple source code.
thanx.
You can easily do that by customizing the header in CSS.
Add the header Style to you accordion.
<mx:Accordion id="accordion"
headerStyleName="accHeader"
width="100%" />
In your CSS
.accHeader {
fillColors: haloSilver, haloBlue;
fillAlphas: 1.0, 0.5;
selectedFillColors: black, black;
}
Or embed your image in here.
You can place that message in your ViewStack.
I use the CanvasButtonAccordionHeader in Flex 3, so not sure if this will work in Flex 4.
But.... in case it's of any use, I create my CanvasButtonAccordianHeader as a custom componant which dispatches an event when the button is clicked:
<CanvasButtonAccordionHeader xmlns="flexlib.containers.accordionClasses.*"
xmlns:mx="http://www.adobe.com/2006/mxml" mouseChildren="true"
<mx:Script>
<![CDATA[
[Bindable]
private var itemName:String;
public function init():void{
itemName=data.name;
}
]]>
</mx:Script>
<mx:Metadata>
[Event(name="homeButtonClicked")]
</mx:Metadata>
<mx:HBox width="100%" horizontalAlign="right" height="100%"
paddingRight="5"
verticalAlign="middle">
<mx:LinkButton label="<>"
click="dispatchEvent(new Event('homeButtonClicked'));"
/>
</mx:HBox>
</CanvasButtonAccordionHeader>
Then I instantiate the custom componant at the bottom of the Accordian as a Header Renderer:
............................................
<mx:headerRenderer>
<mx:Component>
<applicationLayout:AccordionNavHeaderRenderer
homeButtonClicked="outerDocument.dispatchEvent(new Event('homeClick'))"/>
</mx:Component>
</mx:headerRenderer>
</mx:Accordion>
Hope this is of use.

How to load dynamic events in Flex

I have a small flex application.
<mx:Script>
<![CDATA[
import flash.events.Event;
// Event handler function to print a message
// describing the selected Button control.
private function printMessage(event:Event):void {
message.text += event.target.label + " pressed" + "\n";
}
]]>
</mx:Script>
<mx:Panel title="Button Control Example"
height="75%" width="75%" layout="horizontal"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
<mx:VBox>
<mx:Label width="100%" color="blue"
text="Select a Button control."/>
<!-- The button can contain an image, as in the "Button with Icon" button -->
<mx:Button id="iconButton" icon="#Embed('assets/mm-icon.png')" label="Button with Icon"
labelPlacement="right" color="#993300" click="printMessage(event);"/>
<!-- The size of the button and the label attributes can be customized -->
<mx:Button label="Customized Button" color="#993300" toggle="true" selected="true"
textAlign="left" fontStyle="italic" fontSize="13" width="{iconButton.width}"
click="printMessage(event);"/>
<!-- By default, the look and feel of the customized button is
similar to the Default Button. -->
<mx:Button label="Default Button" click="printMessage(event);"/>
</mx:VBox>
<mx:TextArea id="message" text="" editable="false" height="100%" width="100%"
color="#0000FF"/>
</mx:Panel>
What I want to achieve is, I want my user to pass the script as a parameter. so he has the flexibility to do anything with the buttons->like add event, hide the other buttons.
Something like this(below)
<param name="script" value="import flash.events.Event;\n private function printMessage(event:Event):void {\nmessage.text += event.target.label + " pressed" + "\n";\n}">
Thanks.
If I understood, what you want is simply create dynamic event and load it to some component, right? If so in did its very easy to implement.
Just create your own custom event (inherit from Event) or use the Event itself:
var event:Event = new Event("[Your event type here"],[bubbles?],[cancelable?]);
and then add listener to your wanted component to the same "event type".
If you need you can also dispatch this event from wanted component programmatically like this:
[you component].dispatchEvent(event);
but then you have to make sure this component extends EventDispatcher class.
Hope I helped.
Royee

Is it possible to store an array in a DataGridColumn in Flex?

I have a datagrid column with a button that opens a modal dialog box allowing the user to upload multiple files. In the code below, the browseAndUpload() method does that. When the user finished uploading files and closes the upload box the closeUpload() method is called. I know for a fact that the uploaded files are being copied into arrFiles.
The problem I am having is that the repeater will not show the files in arrFiles. Here is the code:
<mx:DataGridColumn id="dgcUpload" width="42" headerText="Uploaded Files"
editable="false">
<mx:itemRenderer>
<mx:Component>
<mx:VBox>
<mx:Script>
<![CDATA[
[Bindable]public var arrFiles:ArrayCollection = new ArrayCollection();
public var fileUpload:FileUpload = new FileUpload();
private function browseAndUpload(event:MouseEvent):void
{
fileUpload = FileUpload(PopUpManager.createPopUp(this, FileUpload, true));
fileUpload.addEventListener(CloseEvent.CLOSE, closeUpload);
fileUpload["btnClose"].addEventListener("click", closeUpload);
}
private function closeUpload(event:Event):void
{
arrFiles = fileUpload.arrFiles;
}
]]>
</mx:Script>
<mx:HBox paddingLeft="3" paddingRight="3">
<mx:Button width="36" label="..." click="browseAndUpload(event)"/>
</mx:HBox>
<mx:Repeater id="rpFiles" dataProvider="{arrFiles}">
<mx:Label text="{FileVO(rpFiles.currentItem).name}"/>
</mx:Repeater>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
Thank you in advance for any insight,
Orville
Got it! I made the following changes:
private function closeUpload(event:Event):void
{
arrFiles = fileUpload.arrFiles;
rpFiles.dataProvider = arrFiles;
}
<mx:Repeater id="rpFiles">
<mx:Label text="{FileVO(rpFiles.currentItem).name}"/>
</mx:Repeater>
You are assigning fileUpload.arrFiles directly to arrFiles. Is the former an Array or ArrayCollection? You might need to do arrFiles = new ArrayCollection(fileUpload.arrFiles);
That being said, I hate flex binding and generally avoid it because it can be unreliable. In your case, I'd write my own AS3 component that implements the ItemRenderer and then assign the repeater's dataprovider manually when it changes. You will have more control over the behavior if you do it that way. And a much easier time debugging.

Resources