Remove Button in ItemRenderer giving error - apache-flex

I am using the following .as file as the component for an itemrenderer in a list. Basically each item is rendered in a TextInput and each TextInput has a remove button as you can see from the code. When clicking the remove button, I want to remove the selectedItem..so I am putting the function removeItem() in MainMxml.xml and calling it from the .as file.
However I am getting an error "Cannot access a method or property of a null object reference". Can you help me out with this error?
The .as file as follows:
package components {
import flash.events.Event;
import flash.events.MouseEvent;
import mx.events.FlexEvent;
import renderers.TextInputRenderer;
import spark.components.Button;
import spark.components.TextInput;
import spark.events.TextOperationEvent;
public class ClearableTextInput extends TextInput {
[SkinPart(required="true")]
public var clearButton:Button;
[Bindable]
public var mainMxml:MainMxml;
public function ClearableTextInput() {
super();
//watch for programmatic changes to text property
this.addEventListener(FlexEvent.VALUE_COMMIT, textChangedHandler, false, 0, true);
//watch for user changes (aka typing) to text property
this.addEventListener(TextOperationEvent.CHANGE, textChangedHandler, false, 0, true);
}
private function textChangedHandler(e:Event):void {
if (clearButton) {
clearButton.visible = (text.length > 0);
}
}
private function clearClick(e:MouseEvent):void {
mainMxml.removeItem();
}
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
if (instance == clearButton) {
clearButton.addEventListener(MouseEvent.CLICK, clearClick);
clearButton.visible = (text != null && text.length > 0);
}
}
override protected function partRemoved(partName:String, instance:Object):void {
super.partRemoved(partName, instance);
if (instance == clearButton) {
clearButton.removeEventListener(MouseEvent.CLICK, clearClick);
}
}
}
}
And the ItemRenderer is as such:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" xmlns:components="components.*" width="100%">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.core.EdgeMetrics;
import mx.core.UIComponent;
import skins.ClearableTextInputSkin;
]]>
</fx:Script>
<components:ClearableTextInput id="clearTxt" text="{data.label}" skinClass="skins.ClearableTextInputSkin" />
</s:ItemRenderer>
I am also setting the clear button in the ClearableTextInputSkin which is shown below:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
minWidth="100" minHeight="22"
alpha.disabled="0.5"
blendMode="normal">
<fx:Metadata>
[HostComponent("components.ClearableTextInput")]
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="normal"/>
<s:State name="disabled"/>
</s:states>
<!-- bg -->
<s:Rect id="border" left="0" right="0" top="0" bottom="0" radiusX="3">
<s:fill>
<s:SolidColor id="bgFill" color="#ffffff" />
</s:fill>
<s:stroke>
<s:SolidColorStroke id="borderStroke" color="#333333" weight="1" />
</s:stroke>
</s:Rect>
<!-- text -->
<s:RichEditableText id="textDisplay" left="4" right="24" top="1" bottom="0"
color="#333333"
verticalAlign="middle" />
<s:Button id="clearButton" right="4" verticalCenter="0" />
</s:SparkSkin>
Your help would be much appreciated.
Many thanks.

The answer can be very very long :)
Starting with your code the problem is in line:
mainMxml.removeItem();
Your mainMxml instance is null and that's why you have your NPE (null pointer exception).
But the code in general shows that you currently don't understand Flex, especially data binding. And of course have problems with app's architecture.
First, your line:
[Bindable]
public var mainMxml:MainMxml;
doesn't do anything.
Data binding is just a way to listen changes of variable annotated with [Bindable] metatag. [Bindable] is not a kind of dependency injection but completely opposite of it.
So nobody set the value of your mainMxml field. And to tell the true, it is not the right way to try to inject value there. Instead of that, you should use Observer design pattern and fire event from your component:
package events {
public class ClearableTextInputEvent extends Event {
public static const PERFORM_CLEAR:String = "performClear";
public function ClearableTextInputEvent(type:String) {
super(type);
}
}
}
So now the component:
package components {
import flash.events.Event;
import flash.events.MouseEvent;
import mx.events.FlexEvent;
import renderers.TextInputRenderer;
import spark.components.Button;
import spark.components.TextInput;
import spark.events.TextOperationEvent;
[Event(name="performClear", type="events.ClearableTextInputEvent")]
public class ClearableTextInput extends TextInput {
[SkinPart(required="true")]
public var clearButton:Button;
public function ClearableTextInput() {
super();
//watch for programmatic changes to text property
this.addEventListener(FlexEvent.VALUE_COMMIT, textChangedHandler, false, 0, true);
//watch for user changes (aka typing) to text property
this.addEventListener(TextOperationEvent.CHANGE, textChangedHandler, false, 0, true);
}
private function textChangedHandler(e:Event):void {
if (clearButton) {
clearButton.visible = (text.length > 0);
}
}
private function clearClick(e:MouseEvent):void {
dispatchEvent(new ClearableTextInputEvent(ClearableTextInputEvent.PERFORM_CLEAR));
}
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
if (instance == clearButton) {
clearButton.addEventListener(MouseEvent.CLICK, clearClick);
clearButton.visible = (text != null && text.length > 0);
}
}
override protected function partRemoved(partName:String, instance:Object):void {
super.partRemoved(partName, instance);
if (instance == clearButton) {
clearButton.removeEventListener(MouseEvent.CLICK, clearClick);
}
}
}
}
Ok. Now our renderer. There we should use event bubbling to inform our list container (I suppose it is an instance of MainMxml) about need to remove row. We should create an event class for that.
NB. You can use the same event class but the problem is your ClearableTextInput component and item renderer have different responsibilities
and ClearableTextInput can be used again in some other renderers. It is good practice to create different events for the different layers of your application for low coupling:
package events {
public class RemoveRowEvent extends Event {
public static const REMOVE_CURRENT_ROW:String = "removeCurrentRow";
public function RemoveRowEvent(type:String) {
super(type, true);
}
}
}
Now your renderer:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" xmlns:components="components.*" width="100%">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.core.EdgeMetrics;
import mx.core.UIComponent;
import skins.ClearableTextInputSkin;
]]>
</fx:Script>
<components:ClearableTextInput id="clearTxt" text="{data.label}" skinClass="skins.ClearableTextInputSkin" performClear="dispatchEvent(new RemoveRowEvent(RemoveRowEvent.REMOVE_CURRENT_ROW))" />
</s:ItemRenderer>
And finally in your list's container (MainMxml instance I suppose):
…
addEventListener(RemoveRowEvent.REMOVE_CURRENT_ROW, onRowRemove);
…
private function onRowRemove(event:RemoveRowEvent):void {
removeItem();
event.stopImmediatePropagation();
}
I wrote this draft in the browser so please fix imports etc. by yourself :)

Related

Get ItemRenderer for a particular cell - Flex DataGrid

I have a datagrid with 2 columns. I need to access the item renderer of the second column whenever column-1 value changes. i.e if value of column 1 is A- need to display text field in column2 and if value is B, i need to show dropdown.
Col1----------Col2
A ---------- DropDown
B ---------- TextBox
A ---------- DropDown
Any Solutions???
public class ItemRendererfroDropTest extends GridItemRenderer
{
private var dropdown:DropDownList;
public function ItemRendererfroDropTest()
{
super();
dropdown=new DropDownList();
dropdown.dataProvider=new ArrayCollection(new Array("ABC","PQR"));
this.addElement(dropdown);
dropdown.addEventListener(FlexEvent.VALUE_COMMIT,dataChanged);
}
private function dataChanged(event:FlexEvent):void
{
owner.dispatchEvent(new CustomEvent(CustomEvent.DATA_CHANGED,true));
}
}
public class ItemRenderlabel extends GridItemRenderer
{
public var wlabel:Label=new Label();
public var checkbox:CheckBox=new CheckBox();
public function ItemRenderlabel()
{
super();
this.addEventListener(CustomEvent.DATA_CHANGED,mappingChanged,true);
this.addElement(wlabel);
}
private function mappingChanged(e:CustomEvent):void
{
Alert.show("asfAS");
}
}
You can get some idea from below code: - Event you can do it only for particular item by using dpHierarchy.itemUpdated() by updating individual row.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
private var dpHierarchy:ArrayCollection= new ArrayCollection([
{name:"A", region: "Arizona"},
{name:"B", region: "Arizona"},
{name:"C", region: "California"},
{name:"D", region: "California"}
]);
private function init():void
{
this.addEventListener(FlexEvent.DATA_CHANGE, changeDataHandler);
}
private function changeDataHandler(event:FlexEvent):void
{
dpHierarchy.refresh();
}
]]>
</fx:Script>
<mx:AdvancedDataGrid id="myADG"
width="100%" height="100%"
variableRowHeight="true" dataProvider="{dpHierarchy}">
<mx:columns>
<mx:AdvancedDataGridColumn dataField="name" headerText="Name" itemRenderer="AddComboboxADG"/>
<mx:AdvancedDataGridColumn dataField="region" headerText="Region" itemRenderer="SelectedCustomComponent"/>
</mx:columns>
</mx:AdvancedDataGrid>
</s:Application>
//AddComboboxADG custom item renderer
<?xml version="1.0" encoding="utf-8"?>
<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true">
<fx:Script>
<![CDATA[
import mx.controls.AdvancedDataGrid;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
import mx.controls.advancedDataGridClasses.AdvancedDataGridHeaderRenderer;
import mx.controls.advancedDataGridClasses.AdvancedDataGridListData;
import mx.events.AdvancedDataGridEvent;
import mx.events.DataGridEvent;
import mx.events.FlexEvent;
import mx.events.ItemClickEvent;
import spark.components.supportClasses.ItemRenderer;
import spark.events.IndexChangeEvent;
protected function comboBoxID_changeHandler(event:IndexChangeEvent):void
{
data.name = comboBoxID.selectedItem;
dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE, true));
}
override public function set data(value:Object):void
{
super.data = value;
if(data.name == "A")
{
comboBoxID.selectedIndex = 0;
}else if(data.name == "B")
{
comboBoxID.selectedIndex = 1;
}else if(data.name == "C")
{
comboBoxID.selectedIndex = 2;
}else
{
comboBoxID.selectedIndex = 3;
}
}
]]>
</fx:Script>
<s:DropDownList id="comboBoxID" change="comboBoxID_changeHandler(event)">
<s:ArrayCollection>
<fx:String>A</fx:String>
<fx:String>B</fx:String>
<fx:String>C</fx:String>
<fx:String>D</fx:String>
</s:ArrayCollection>
</s:DropDownList>
</s:MXAdvancedDataGridItemRenderer>
//SelectedCustomComponent custom item renderer
<?xml version="1.0" encoding="utf-8"?>
<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true">
<fx:Script>
<![CDATA[
override public function set data(value:Object):void
{
super.data = value;
customFirstDropDown.visible = customTextInput.visible = customSecondDropDown.visible = lblData.visible = false;
if(data.name == "A")
{
customFirstDropDown.visible = true;
}else if(data.name == "B")
{
customTextInput.visible = true;
}else if(data.name == "C")
{
customSecondDropDown.visible = true;
}else
{
lblData.visible = true;
}
}
]]>
</fx:Script>
<s:DropDownList id="customFirstDropDown" visible="false" selectedIndex="0">
<s:ArrayCollection>
<fx:String>First</fx:String>
<fx:String>Second</fx:String>
<fx:String>Third</fx:String>
</s:ArrayCollection>
</s:DropDownList>
<s:TextInput id="customTextInput" visible="false" text="Selected"/>
<s:DropDownList id="customSecondDropDown" visible="false" selectedIndex="0">
<s:ArrayCollection>
<fx:String>1</fx:String>
<fx:String>2</fx:String>
<fx:String>3</fx:String>
</s:ArrayCollection>
</s:DropDownList>
<s:Label id="lblData" visible="false" text="Selected"/>
</s:MXAdvancedDataGridItemRenderer>
Create Item renderer using ViewStack with views as required, and override data function as normally done for item renderer, to set active child of container base of field, If you wants to set Active child on fly see this post
Hopes that helps

How to create a custom Flex 4 button with 3 labels

I would like to create a custom Button component with three labels: left-, center-, and right-justified. I can't just use the label justification property, because I want to use all 3 labels at the same time.
I'm familiar with creating custom components, but I've never tried to build one quite like this before...
Here's what I have so far:
<?xml version="1.0" encoding="utf-8"?>
<s:Button
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
private var labelContentL:String;
private var labelContentC:String;
private var labelContentR:String;
public function set labelL(value:String):void
{
labelContentL = value;
}
public function set labelC(value:String):void
{
labelContentC = value;
}
public function set labelR(value:String):void
{
labelContentR = value;
}
public function get labelL():String
{
return labelContentL;
}
public function get labelC():String
{
return labelContentC;
}
public function get labelR():String
{
return labelContentR;
}
]]>
</fx:Script>
<s:Label id="l" width="100%" text="{labelContentL}" textAlign="left" paddingLeft="10" />
<s:Label id="c" width="100%" text="{labelContentC}" textAlign="center" />
<s:Label id="r" width="100%" text="{labelContentR}" textAlign="right" paddingRight="10" />
</s:Button>
The labels won't change after the button is created, so I'm not worried about the missing [Bindable] metadata.
I'm stuck right now, getting the following compiler error:
Multiple initializer values for default property, 'label', of type 'String'.
...for each of the 3 <s:Label> lines.
Based on this answer to a similar question, I tried adding label="" to my <s:Button> declaration, but that just adds another error.
How do I fix this?
Your problem is that a tag named label under the button tag isn't an item of type label, it's the label used on the button, and is of type string.
Why not do it as a skin, rather than a custom component?
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<!-- host component -->
<fx:Metadata>
[HostComponent("ThreeLabelButton")]
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="disabled" />
<s:State name="down" />
<s:State name="over" />
<s:State name="up" />
</s:states>
<s:Rect bottomLeftRadiusX="5"
bottomRightRadiusX="5"
topLeftRadiusX="5"
topRightRadiusX="5"
top="0" left="0" right="0" bottom="0">
<s:fill>
<s:SolidColor color.up="#CCCCCC" color.over="#555555" color.down="#888888" />
</s:fill>
</s:Rect>
<mx:Label id="leftLabel" text="{hostComponent.leftText}" left="0" />
<mx:Label id="rightLabel" text="{hostComponent.rightText}" right="0" />
<mx:Label id="centerLabel" text="{hostComponent.centerText}" left="{(this.width - centerLabel.width) / 2}" />
</s:Skin>
This will work with this class:
import mx.controls.Label;
import spark.components.supportClasses.ButtonBase;
public class ThreeLabelButtonComponent extends ButtonBase
{
public function ThreeLabelButtonComponent()
{
super();
}
[SkinPart]
public var leftLabel:Label;
[SkinPart]
public var rightLabel:Label;
[SkinPart]
public var centerLabel:Label;
[Bindable]
public var leftText:String;
[Bindable]
public var rightText:String;
[Bindable]
public var centerText:String;
protected override function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if(instance === leftLabel)
{
leftLabel.text = leftText;
}
if(instance === rightLabel)
{
rightLabel.text = rightText;
}
if(instance === centerLabel)
{
centerLabel.text = centerText;
}
}
}

TypeError: Error #1009: Cannot access a property or method of a null object reference

I get this error when i launch the application(flash type with dismiss all and continue) and i'm out of ideas:
TypeError: Error #1009: Cannot access
a property or method of a null object
reference. at
Magazin/xmlService_resultHandler()[D:\Documents
and Settings\chechu\Adobe Flash
Builder 4\Magazin\src\Magazin.mxml:41]
at
Magazin/__xmlService_result()[D:\Documents
and Settings\chechu\Adobe Flash
Builder 4\Magazin\src\Magazin.mxml:64]
at
flash.events::EventDispatcher/dispatchEventFunction()
at
flash.events::EventDispatcher/dispatchEvent()
at
HTTPOperation/http://www.adobe.com/2006/flex/mx/internal::dispatchRpcEvent()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\http\HTTPService.as:989]
at
mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::resultHandler()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:318]
at
mx.rpc::Responder/result()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\Responder.as:56]
at
mx.rpc::AsyncRequest/acknowledge()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:84]
at
DirectHTTPMessageResponder/completeHandler()[E:\dev\4.x\frameworks\projects\rpc\src\mx\messaging\channels\DirectHTTPChannel.as:446]
at
flash.events::EventDispatcher/dispatchEventFunction()
at
flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
The main application:
import events.ProductEvent;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import valueObject.ImageClass;
[Bindable]
public var imagesCollection:ArrayCollection;
protected function xmlService_faultHandler(event:FaultEvent):void
{
Alert.show("meeah");
}
protected function xmlService_resultHandler(event:ResultEvent):void
{
var imageCollection:ArrayCollection=event.result.Images.image ;
var imData:ImageClass;
for each(var im:Object in imageCollection)
{
imData=new ImageClass();
imData.url=im.url;
imData.big_url=im.big_url;
imData.cat=im.cat;
imData.descript=im.descript;
imData.price=im.price;
imagesCollection.addItem(imData); line:41
}
Alert.show("gg");
}
[Bindable]
public var mama:ArrayCollection=new ArrayCollection();
protected function gallery1_addToCartHandler(event:ProductEvent):void
{
mama.addItem(event);
currentState="cart";
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="cart"/>
</s:states>
<fx:Declarations>
<s:HTTPService id="xmlService" line 64
url="dataXml/pics.xml" fault="xmlService_faultHandler(event)"
result="xmlService_resultHandler(event)"/>
</fx:Declarations>
<components:Gallery imagesArray="{imagesCollection}" addToCart="gallery1_addToCartHandler(event)" />
<components:cart x="500" y="300" itemRenderer="components.CartRenderer" dataProvider="{mama}" />
</s:Application>
The Gallery component:
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" >
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Metadata>
[Event(name="addToCart",type="events.ProductEvent")]
</fx:Metadata>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import events.ProductEvent;
import mx.collections.ArrayCollection;
import valueObject.ImageClass;
[Bindable]
public var imagesArray:ArrayCollection;
public function goa_clickHandler(event:MouseEvent):void
{
for (var i:uint=0; i<imagesArray.length;i++)
{
var objEvent:ProductEvent=new ProductEvent("addToCart",true);
objEvent.imData=imagesArray[i] ;
dispatchEvent(objEvent);
}
}
]]>
</fx:Script>
<s:SkinnableDataContainer id="cont" dataProvider="{imagesArray}">
<s:itemRenderer >
<fx:Component>
<s:ItemRenderer>
<s:HGroup>
<s:Label id="gagal" text="{data.price}"/>
<mx:Image source="{data.url}" width="50" height="50" />
<s:Button id="goa" label="buy" click="outerDocument.goa_clickHandler(event)"/>
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:SkinnableDataContainer>
</s:Group>
The ProductEvent class:
package events
{
import flash.events.Event;
import valueObject.ImageClass;
[Bindable]
public class ProductEvent extends Event
{
public var imData:ImageClass;
public function ProductEvent(type:String,bubbles:Boolean=true)
{
super(type,bubbles);
}
override public function clone():Event
{
var eventOb:ProductEvent=new ProductEvent(type,bubbles);
eventOb.imData=this.imData;
return eventOb;
}
}
The ImageClass:
package valueObject
{
[Bindable]
public class ImageClass
{
public var url:String;
public var big_url:String;
public var descript:String;
public var price:String;
public var cat:String;
public function ImageClass()
{
/*this.url=url;
this.big_url=big_url;
this.descript=descript;
this.price=price;
this.cat=cat;*/
}
}
}
and the xml:
<?xml version="1.0"?>
<Images>
<image>
<url>poze/pics/IMG_1163.jpg</url>
<big_url>poze/big_pics/IMG_1163.jpg </big_url>
<descript>P</descript>
<price>99.99</price>
<cat>A</cat>
</image>
<image>
<url>poze/pics/IMG_1175.jpg</url>
<big_url>poze/big_pics/IMG_1175.jpg</big_url>
<descript>U</descript>
<price>99.99</price>
<cat>A</cat>
</image>
<image>
<url>poze/pics/IMG_1186.jpg</url>
<big_url>poze/big_pics/IMG_1186.jpg</big_url>
<descript>L</descript>
<price>99.99</price>
<cat>A</cat>
</image>
You're accessing imagesCollection variable in line 41, but haven't initialized it - it still contains null
Either change
[Bindable]
public var imagesCollection:ArrayCollection;
To
[Bindable]
public var imagesCollection:ArrayCollection = new ArrayCollection();
or add
imagesCollection = new ArrayCollection();
to the beginning of xmlService_resultHandler method.
Remember...
Whenever there is a null reference error then you need to initialize the variable that you are using.
Say if you are using Array or ArrayCollection
you need to do: yourArrayVarriable = new Array(); inside the function or
you need to do: yourArrayCollectionVarriable = new ArrayCollection(); inside the function
and then start using yourArrayVarriable or yourArrayCollectionVarriable to store the values

Keyboard Application - Best way to have multiple buttons add letter to textinput? Use event handlers?

I'm working on an application and I am building a "Keyboard" component for it. There are 30 keys on the keyboard and it doesnt seem to make practical sense to create an event handler for each button. When the button is clicked, its label should be sent out to a function which adds it to a textinput field.
Should I just create a "click=SomeFunction(Button.label)" for each button or is there a better/faster/less processor intensive way to do it?
there is a much easier way. you can extend the button component and create a default click even that bubbles up. You then can have the parent component listening for the event. Here is a quick example:
myButton.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
click="clickKeyHandler( event );">
<mx:Metadata>
[Event(name="keyboardClickEvent", type="com.KeyboardEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import com.KeyboardEvent;
protected function clickKeyHandler( event:MouseEvent ):void{
dispatchEvent( new KeyboardEvent( this.label ) );
}
]]>
</mx:Script>
</mx:Button>
com.KeyboardEvent:
package com
{
import flash.events.Event;
public class KeyboardEvent extends Event
{
public static const KEYBOARD_CLICK_EVENT:String = "keyboardClickEvent";
private var _value:String;
public function get value():String{
return _value;
}
public function KeyboardEvent( value:String = "" )
{
super( KEYBOARD_CLICK_EVENT, true );
_value = value;
}
override public function clone() : Event {
return new KeyboardEvent( _value );
}
}
}
usage in app:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="initApp();" xmlns:local="*">
<mx:Script>
<![CDATA[
import com.KeyboardEvent;
private function initApp():void{
this.addEventListener( KeyboardEvent.KEYBOARD_CLICK_EVENT, keyboardHandler);
}
private function keyboardHandler( event:KeyboardEvent ):void{
trace( event.value );
}
]]>
</mx:Script>
<local:myButton label="1" />
<local:myButton label="2" />
<local:myButton label="3" />
<local:myButton label="4" />
</mx:Application>

Mate not catching Event in EventMap [Flex]

In my AIR application I am having problems catching dispatched events in my eventmap.
The class that is dispatching the events looks like this:
Shortcuts.as
[Event(name="centeredZoomOut", type="flash.events.Event")]
public class Shortcuts extends EventDispatcher
{
// Event Names
public static const CENTERED_ZOOM_OUT:String = "centeredZoomOut";
public function Shortcuts(target:IEventDispatcher=null)
{
super(target);
NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
private function onKeyUp(event:KeyboardEvent):void
{
this.dispatchEvent(new Event(CENTERED_ZOOM_OUT, true));
}
}
I know that the event is getting dispatched from debugging it, but it is not getting caught by the following eventmap.
ShortcutMap.mxml
<?xml version="1.0" encoding="utf-8"?>
<EventMap
xmlns="http://mate.asfusion.com/"
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import models.Shortcuts;
]]>
</mx:Script>
<EventHandlers type="{ Shortcuts.CENTERED_ZOOM_OUT }">
<MethodInvoker generator="{ShortCutExample}" method="showAlert" arguments="{['centeredZoom']}" />
</EventHandlers>
Here is the main application file called "ShortCutExample"
ShortCutExample.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:maps="maps.*"
layout="absolute"
creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import models.Shortcuts;
private var shortcuts:Shortcuts;
private function init():void
{
this.shortcuts = new Shortcuts();
}
public function showAlert(value:String):void
{
Alert.show(value);
}
]]>
</mx:Script>
<maps:ShortcutMap/>
</mx:WindowedApplication>
Why is my eventmap not catching the event?
Because I was not adding the object to the display list and it did not extend DisplayObject the dispatched events were not being caught by the eventmap. To solve this problem create a private variable of type GlobalDispatcher and dispatch your events from that variable.
private var dispatcher:GlobalDispatcher = new GlobalDispatcher();
...
this.dispatcher.dispatchEvent(new ShortCutEvent(ShortCutEvent.CENTERED_ZOOM_OUT, true));

Resources