I am kind of puzzled and not sure how to tackle this issue: Got two comboxes with dataproviders. Also, I created a separate index.as in /as folder. I have these two functions:
In my .mxml page, I have :
<mx:FormItem label="Property Code:" id="fi_propertyCode" width="100%">
<mx:ComboBox id="propertyCode" width="50%" dataProvider="{qry_communites}" change="showPropertyCode()" />
</mx:FormItem>
<mx:FormItem label="Utility Type:" id="fi_utilityType" width="100%">
<mx:ComboBox id="utilityType" width="50%" dataProvider="{qry_utilityTypes}" change="showUtilityType()" />
</mx:FormItem>
and in my index.as, I have:
private function showPropertyCode():void {
mx.controls.Alert.show(propertyCode.selectedItem.label, propertyCode.selectedItem.data);
}
private function showUtilityType():void {
mx.controls.Alert.show(utilityType.selectedItem.label, utilityType.selectedItem.data);
}
I get an error saying
Access of undefined property utilityType.
The funny thing is I don't get this error for "propertyCode". Moreover, If I copy pasyte showUtilityType() function and put inside my .mxml page, I don't get this error either. Btw. I have :
....
in my .mxml page. What should I do? How can I get rid of this error? Why does Flex see propertyCode combobox but not utilityType combobox? I would rather keep index.as as it is. Thanks in advance.
That's strange. Did you try specifying the script using the source attribute?
<mx:Script source="../as/index.as"/>
Related
Trying to validate the input in my data grid, I am using a function (taken from an Adobe example).
This is how the grid goes:
<mx:DataGrid id="CashGrid" dataProvider="{cash}" editable="true" itemEditBeginning="allowForEdit(event)" itemEditEnd="formatData(event);" sortableColumns="false">
<mx:columns>
<mx:DataGridColumn textAlign="left" dataField="curName" headerText="Currency" />
<mx:DataGridColumn textAlign="right" dataField="value" headerText="Value" width="150">
</mx:columns>
</mx:DataGrid>
And here is the function from the AS part
public function formatData(event:DataGridEvent):void
{
if (event.reason == DataGridEventReason.CANCELLED)
{
// Do not update cell.
return;
}
var newData:String= TextInput(event.currentTarget.itemEditorInstance).text;
// Determine if the new value is an empty String.
if(newData == "")
{
event.preventDefault();
TextInput(cashGrid.itemEditorInstance).errorString=
"Enter a valid string.";
return;
}
}
Although it works in the source example, in my example, on editing said grid, an error pops up saying
TypeError: Error #1034: Type Coercion failed: cannot convert mx.controls::TextInput#f093c29 to spark.components.TextInput.
Trying to
import mx.controls.TextInput;
tells me
Can not resolve a multiname reference unambiguously. spark.components.TextInput.
I guess there is some confusion with the namespaces, but I have no idea how to make this work.
Help!
Thanks
I cannot reproduce the error with the given code. It's working fine on my end. Please send me the code for allowForEdit(event) as well.
Which SDK version are you using?
What is the root application namespace? Please paste the entire application namespace.
I am using a custom itemEditor for my DataGrid.
The itemEditor has a simple TextField as a component.
But when ever i am clicking the cell i am getting an error as :
ReferenceError: Error #1069: Property text not found on editors.customItemEditor and there is no default value.
at mx.controls::DataGrid/itemEditorItemEditEndHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\DataGrid.as:4827]
Plz help me to resolve this issue.
My Opinion is that the error is coming for the "text" field. But i havn't accessed "text" field or used it anywhere in my code.
Regards,
Ravi
i solved the problem with commiting incluting "return data["selected"].toString()" into get text:
<mx:DataGridColumn dataField="selected" rendererIsEditor="true" >
<mx:itemRenderer>
<fx:Component>
<mx:Box styleName="" width="100%" height="100%" backgroundAlpha="0.0"
horizontalAlign="center" verticalAlign="middle">
<fx:Script>
<![CDATA[
public function get text():String
{
return data["selected"].toString();
}
public function set text(value:String):void
{
}
protected function checkbox1_clickHandler(event:MouseEvent):void
{
data["selected"]=event.target["selected"];
}
]]>
</fx:Script>
<mx:CheckBox selected="{data.selected}" click="checkbox1_clickHandler(event)"/>
</mx:Box>
</fx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
Taken from http://livedocs.adobe.com/flex/3/html/help.html?content=celleditor_8.html
By default, Flex expects an item editor to return a single value to the list-based control. You use the editorDataField property of the list-based control to specify the property of the item editor that contains the new data. Flex converts the value to the appropriate data type for the cell.
The default item editor is a TextInput control. Therefore, the default value of the editorDataField property is "text", which corresponds to the text property of the TextInput control. If you specify a custom item editor, you also set the editorDataField property to the appropriate property of the item editor
I am still Struck in this error but i think there is a hope of coming out of it.... :)
If we take TextInput as the itemEditor, like:
dataGridColumn.itemEditor = new ClassFactory(TextInput);
Then there was no problem as "text" is being internally defined inside TextInput.as.
On a similar note if i copy set text and get text inside our custom Editor, then its working fine.. only problem that is
coming is regarding commiting the changed values.
I am working on it, hope i'll be able to sort it out.
P.S.: I am a newbie here, so plz pardon me of any idiotic RnD... :p
I'm working on Flash Builder with latest flex SDK.
I have a problem getting the value radioButton of the selceted radio button inside a form:
<mx:Form id="form_new_contribution">
<mx:FormItem label="Contribution type" includeIn="project_contributions">
<mx:RadioButtonGroup id="myG" enabled="true" />
<mx:RadioButton id="subtitle" label="subtitle" groupName="{myG}" value="subtitle"/>
<mx:RadioButton id="note" label="notes / chapters" groupName="{myG}" value="note"/>
</mx:FormItem>
</mx:Form>
the function is:
protected function button_add_new_clickHandler(event:MouseEvent):void{
Alert.show(myG.selectedValue.toString());
}
I tried also:
Alert.show(myG.selection.toString());
bothe codes show error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
and if It only works if I put :
Alert.show(myG.toString());
it alerts : Object RadioButtonGroup
thanx for any hints, and sorry for the long message :)
The only thing I see wrong here is that the groupName property of RadioButton is a string, not a curly-braced reference to a RadioButtonGroup.
You should render it as:
<mx:RadioButton id="subtitle" label="subtitle" groupName="myG" value="subtitle"/>
not
<mx:RadioButton id="subtitle" label="subtitle" groupName="{myG}" value="subtitle"/>
Or you can also use the group property with an RBG reference:
<mx:RadioButton id="subtitle" label="subtitle" group="{myG}" value="subtitle"/>
When are you calling this alert function? Is it possible that neither of the radio buttons are selected when the alert is called, thus selection and selectedValue are accurately returned as null?
<mx:DataGrid x="10" y="10" width="180" height="302" id="dgActions" dataProvider="{actionCollection}">
<mx:columns>
<mx:DataGridColumn headerText="Action" dataField="name"/>
<mx:DataGridColumn headerText="" dataField="setting" width="30" rendererIsEditor="true">
<mx:itemRenderer >
<mx:Component>
<mx:Box width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
<mx:CheckBox selected="{data.setting}" click="setActionSetting()">
<mx:Script>
<![CDATA[
private function setActionSetting(){
data.setting = String(this.selected);
}
]]>
</mx:Script>
</mx:CheckBox>
</mx:Box>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
For some reason I'm getting an error at the data.setting= String(this.selected) line which says "Access to possibly indefined property selected through a reference with static type".
[edit] The solution to the above problem (albeit not the entire mess) was that once you're inside a <mx:Component> tag you are within the scope of said component. To get access to the script and nodes outside this component you have to use the outerDocument object.
[end edit]
I'm not sure what it's expecting, I'm assuming that it's going to pass the true/false value of the selected(ness) of the checkbox into the method, but it appears not to understand what "this" is, in this context.
Am I doing something obviously wrong? All I want is for the data source to reflect the change in the status that it initially fed into the checkbox.
EDIT:
I just noticed that when I add trace('foo') to the function, it never writes anything back to the console. Is the checkbox's native behavior (and event capture) preventing it from bubbling past to my function?
Additionally, when I add references to objects outside in the rest of the document, it tells me it doesn't recognize them. I'm totally confused as to how Flex scopes things... any additional guidance or links to reference would be really handy.
this in this (ha) case is referring to the component renderer and not the surrounding class (or the checkbox, datagridcolumn, datagrid, etc). You are really better off breaking the renderer out into a real component so you won't be obfuscating the scope as much as when the inline component approach is used.
Peter Ent's series on itemRenderers is extremely useful and should explain everything you want to know on the subject.
If I had to guess "this" is the mx:Script element, try "parent.selected".
CheckBox.selected requires a Boolean value. The fact that you're setting data.setting to a String value tells me that data.setting is NOT a Boolean.
So, after a great deal of agony I have finally figured out how this all works....
Joel is on the right track, this doesn't refer to what you would hope it would refer to (namely the checkbox). Additionally, even if you pass this into the method FROM the checkbox node, it refers to the parent wrapper class and not the checkbox itself. So, the solution is to pass in the event, and then access its target, which FINALLY is the checkbox. And then you're home.
In other words...
<mx:CheckBox selected="{data.setting}" click="setActionSetting(event)">
<mx:Script>
<![CDATA[
private function setActionSetting(e:Event):void{
data.setting = e.target.selected;
trace("n=" + data.name + " set to " + data.setting);
//the name is the other piece of the data that I omitted for clarity
}
]]>
</mx:Script>
</mx:CheckBox>
I've got an object that contains a dozen or so fields I want to bind to form elements, so that I can use that object to send the data back to the server to be saved.
Definition of my container object:
private static const emptyLink:Object = {
id: -1, title:'',
trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'',
linkTitle:'', linkBody:'',
answer1:'',answer2:'',answer3:'',answer4:'',answer5:''
};
[Bindable] public var currentLink:Object = emptyLink;
currentLink is assigned at runtime to a specific index from an ArrayCollection, I'm just using the emptyLink object for initialization purposes, mostly.
<mx:Panel id="triggerPanel" title="Trigger" width="33%">
<mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:TextInput id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" />
<mx:TextInput id="trigger2" width="100%" textAlign="left" text="{currentLink.trigger2}" />
<mx:TextInput id="trigger3" width="100%" textAlign="left" text="{currentLink.trigger3}" />
<mx:TextInput id="trigger4" width="100%" textAlign="left" text="{currentLink.trigger4}" />
<mx:TextInput id="trigger5" width="100%" textAlign="left" text="{currentLink.trigger5}" />
</mx:VBox>
</mx:Panel>
Of course, this compiles and displays just fine, but there are runtime warnings for each instance:
warning: unable to bind to property 'trigger1' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger2' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger3' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger4' on class 'Object' (class is not an IEventDispatcher)
warning: unable to bind to property 'trigger5' on class 'Object' (class is not an IEventDispatcher)
And the currentLink object is not updated when the TextInput fields are changed.
The obvious answer is that my object needs to be an instance of a class that implements IEventDispatcher. What that answer doesn't tell me is the particulars of implementing that interface (what's required? what's not?), and if there is a simpler way to do this -- like a built in class that will gladly accept my custom properties and allow for binding, without me having to worry about the particulars of implementing the interface.
Does such a class exist? If not, what's the bare minimum and/or accepted standard for accomplishing this task?
You need to use ObjectProxy (as Chetan mentions) - but you also need to use valueCommit to get the text you enter in the input BACK into your object:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.utils.ObjectProxy;
private static const emptyLink:Object = {
id: -1, title:'',
trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'',
linkTitle:'', linkBody:'',
answer1:'',answer2:'',answer3:'',answer4:'',answer5:''
};
[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);
private function handleClick():void
{
trace(currentLink.trigger1);
}
]]>
</mx:Script>
<mx:Panel id="triggerPanel" title="Trigger" width="33%">
<mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:TextInput id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" valueCommit="{currentLink.trigger1 = trigger1.text;}"/>
<mx:Button label="Click" click="handleClick()"/>
</mx:VBox>
</mx:Panel>
</mx:WindowedApplication>
Object doesn't dispatch events. Although you have made the variable Bindable, the properties of the object referenced by the variable currentLink can not be bound.
Use ObjectProxy instead.
[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);
The first thing you'll want to know is that binding in Flex 3 is not bidirectional. The binding expression will ensure that if the source of the binding expression (currentLink.trigger1) changes that the target (TextInput) will receive notification of the change and update accordingly. If you want the binding to go in the other direction, there are at least two ways to do this:
Use the mx:Binding tag to direct TextInput.text back to the object
Use BindingUtils to do this programmatically instead.
In Flex 4 they are introducing a new syntax for bidirectional binding #{some.binding.expression} but it's not available in Flex 3.
On the 2nd part: the error that you're receiving is because you are binding to a "generic" prototype Object. When you apply the [Bindable] metadata tag to a property or class, the MXMLC compiler generates AS code that includes use of binding utilities and property change watchers to do make the binding happen. However you can't make the prototype Object do this since it's a built-in. You can create a custom ActionScript class which is bindable (or has certain properties bindable). The MXMLC compiler will generate a class which implements IEventDispatcher and therefore supports binding. This has the advantage of being faster than prototype objects and also gives you compile-time checking, i.e. you will receive a compiler error if you reference an invalid property.
The other alternative is to wrap your prototype in ObjectProxy as one of the other SO members has suggested.
Just a tip on how to find out the offending code in a larger project - put a breakpoint on the two
trace("warning: unable to bind to property '"
lines in the SDK's PropertyWatcher class (Navigate > Open Type > ...). Stacktrace will then help you find the ui component that holds the broken binding.
In general, the reason why you get "unable to bind to property foo on a class, is because you are either missing a getter or setter for foo. You could also make foo scoped to a public variable, (although this breaks encapsulation)
So you need Both of these to make it go away:
public function set foo (o:FooObject) : void {
...
}
or
public function get foo() : FooObject {
...
}
Here's the livedocs reference for the interface. It's pretty much what would be obvious.
To quote:
In general, the easiest way for a user-defined class to gain event dispatching capabilities is to extend EventDispatcher.
Hence,
private static const emptyLink:EventDispatcher = {
I haven't been using Flex for very long, and this might not fit your requirements, but why not use XML? I believe you can set the TextInput text value to attributes in the XML.
I'm using pseudo-code, but something like this makes sense to me:
[Bindable] private static const currentLink:XML = <root>
<trigger1 value=""/>
<trigger2 value="" />
</root>;
...
<mx:TextInput id="trigger1" width ... text="{currentLink.trigger1.#value}" />
Something like this, perhaps?