I've made a custom component based on MenuBar. This is the code
<?xml version="1.0" encoding="utf-8"?>
<mx:MenuBar xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%"
labelField="#label">
<mx:XMLList>
<menuitem label="Website" />
</mx:XMLList>
</mx:MenuBar>
The problem is that the "Website" isn't displayed.
EDIT
I found the correct syntax and it's working now
<?xml version="1.0" encoding="utf-8"?>
<mx:MenuBar xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%"
labelField="#label" dataProvider="{menuXmlListCollection}">
<mx:XMLListCollection id="menuXmlListCollection">
<mx:XMLList>
<menuitem label="Website" />
</mx:XMLList>
</mx:XMLListCollection>
</mx:MenuBar>
You can do this same thing with a ArrayCollection:
private var menuXmlListCollection: ArrayCollection = new ArrayCollection([
{ label: "Website"},
{ label: "Webmail"},
{ label: "Blog"}];
Related
Working through a series of Adobe AIR examples I have encountered a compilation error with one of them that I have distilled into the following demo application file
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.events.MenuEvent;
private static const MENU_DEMO:String = "Demo...";
private function onMenuItemClick(evt:MenuEvent):void
{
switch(evt.label)
{
case MENU_DEMO:
break;
}
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%" paddingBottom="5">
<mx:MenuBar id="menuBar"
width="100%"
labelField="#label"
itemClick="onMenuItemClick(event);">
<mx:XMLList>
<menuitem label="Error">
<menuitem label="{MENU_DEMO}" />
</menuitem>
</mx:XMLList>
</mx:MenuBar>
</mx:VBox>
</mx:WindowedApplication>
for which the descriptor file is
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.0.M6">
<id>ErrorDemo</id>
<filename>ErrorDemo</filename>
<name>Error Demo</name>
<version>v0.1</version>
<description>Demo undefined property error</description>
<copyright></copyright>
<initialWindow>
<title>Error Demo</title>
<content>ErrorDemo.swf</content>
<systemChrome>standard</systemChrome>
<transparent>false</transparent>
<visible>true</visible>
</initialWindow>
</application>
Compilation produces the following output
C:\Projects\AIR\ErrorDemo>amxmlc ErrorDemo.mxml
Loading configuration file C:\Projects\flex_sdk_4.6\frameworks\air-config.xml
C:\Projects\AIR\ErrorDemo\ErrorDemo.mxml(28): Error: Access of undefined property _ErrorDemo_XMLList1.
<menuitem label="{MENU_DEMO}" />
The problem seems to be down to the use of the static const {MENU_DEMO} bound to the menuitem tag's label attribute because substituting it with text leads to no compilation error. Adobe's Using Flex 4.6 documentation states that static constants can be used as data binding sources, but maybe not in the way they're used here. Does anyone know what the problem is with using them in this way?
To clarify: replacing the bound constant reference {MENU_DEMO} with the string literal Demo... produces the following expected output. But using a string literal in place of the bound constant reference defeats the purpose of using a bound constant. Which is what seems to generate the error, and is the point of this post.
try adding [Bindable] before private static const MENU_DEMO:String = "Demo...";
it becomes:
[Bindable]
private static const MENU_DEMO:String = "Demo...";
I don't use Flex but from some research about your problem I noticed...
(1)
Your code has:
<menuitem label="{MENU_DEMO}" />
Try setting that as:
<menuitem label text="{MENU_DEMO}" />
(2)
Also since you say itemClick="onMenuItemClick(event);" shouldn't that be backed up by:
import mx.events.ItemClickEvent;
(3)
What is the expected result if your code compiled correctly?
I can't (or won't) test any Flex code so let me know if this works or errors...
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.events.MenuEvent;
import mx.events.ItemClickEvent; //add this
[Bindable]
public var MENU_DEMO:String = "Demo...";
public function onMenuItemClick(evt:MenuEvent):void //or try... (evt:MenuEvent = null):void
{
if (evt.label.text == MENU_DEMO) //untested
{
//do something here
evt.label.text = "Changed...";
}
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%" paddingBottom="5">
<mx:MenuBar id="menuBar"
width="100%"
labelField="#label"
itemClick="onMenuItemClick(event);">
<mx:XMLList xmlns="">
<menuitem label="Error" />
<menuitem label text="{MENU_DEMO}" />
</menuitem>
</mx:XMLList>
</mx:MenuBar>
</mx:VBox>
</mx:WindowedApplication>
For anyone interested in what a Flex 4 version of the mxml code looks like, here is what I came up with, following #ProgrammerDancuk's suggestion, who really should receive credit
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.events.MenuEvent;
private static const MENU_DEMO:String = "Demo...";
private function onMenuItemClick(evt:MenuEvent):void
{
switch(evt.label)
{
case MENU_DEMO:
break;
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<fx:XMLList id="demoMenu">
<menuitem label="Error">
<menuitem label="{MENU_DEMO}" />
</menuitem>
</fx:XMLList>
</fx:Declarations>
<mx:VBox width="100%" height="100%" paddingBottom="5">
<mx:MenuBar id="menuBar"
width="100%"
labelField="#label"
itemClick="onMenuItemClick(event);">
<mx:dataProvider>
{demoMenu}
</mx:dataProvider>
</mx:MenuBar>
</mx:VBox>
</s:WindowedApplication>
I have an example custom mxml component CustomRadio
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:RadioButton id="radio" />
<mx:Script>
public override function set label(value:String):void {
this.radio.label = value;
}
public override function get label():String {
return this.radio.label;
}
</mx:Script>
</mx:VBox>
and an application
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*">
<local:CustomRadio label="xxx" />
</mx:WindowedApplication>
And I get Null reference arror in set label saying this.radio is null. Why ?
The RadioButton tag needs to encompass the Script tag. The way you have it now, the script tag is part of the VBox only. Since you are using the 'this' pointer, it's referring to the VBox.
This is my code, the expected menu would show grandparent > parent > child.
However, the 'parent' item is not being displayed, instead, it shows 'child' directly under 'grandparent'.
<mx:Script>
<![CDATA[
// Import the Menu control.
import mx.controls.Menu;
// Create and display the Menu control.
private function createAndShow():void {
var myMenu:Menu = Menu.createMenu(null, myMenuData, false);
myMenu.labelField="#label";
myMenu.show(10, 10);
}
]]>
</mx:Script>
<!-- Define the menu data. -->
<mx:XML format="e4x" id="myMenuData">
<root>
<menuitem label="grandparent">
<menuitem label="parent">
<menuitem label="child"/>
</menuitem>
</menuitem>
</root>
</mx:XML>
<mx:VBox>
<!-- Define a Button control to open the menu -->
<mx:Button id="myButton"
label="Open Menu"
click="createAndShow();"/>
</mx:VBox>
The funny thing is, when I add a second parent, it does show the menu correctly.
Can anyone explain what is going on here and how I can solve this?
I took your code, threw it in a project of my own and got the same results you did. I then added another parent to your XML and everything works fine. I am guessing that if you only have one parent node there really isnt a need need to show it so it skips to the child.
Added second parent below:
<root>
<menuitem label="grandparent">
<menuitem label="parent1">
<menuitem label="child"/>
</menuitem>
<menuitem label="parent2">
<menuitem label="child"/>
</menuitem>
</menuitem>
</root>
Try some thing like below: -
<?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">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<fx:XML id="myMenuData" >
<menuitem label="grandparent">
<menuitem label="Uparent">
<menuitem label="child"/>
</menuitem>
</menuitem>
</fx:XML>
</fx:Declarations>
<fx:Script>
<![CDATA[
// Import the Menu control.
import mx.controls.Menu;
// Create and display the Menu control.
private function createAndShow():void {
var myMenu:Menu = Menu.createMenu(null, myMenuData, true);
myMenu.labelField="#label";
myMenu.show(10, 10);
}
]]>
</fx:Script>
<!-- Define the menu data. -->
<mx:VBox>
<!-- Define a Button control to open the menu -->
<mx:Button id="myButton"
label="Open Menu"
click="createAndShow();"/>
</mx:VBox>
</s:Application>
I have a native menu item with a shortcut for a simple letter like "F".
<s:menu>
<mx:FlexNativeMenu id="mainMenu"
dataProvider="{menuData}"
labelField="#label"
keyEquivalentField="#keyEquivalent"
showRoot="false" />
</s:menu>
<fx:Declarations>
<fx:XML format="e4x" id="menuData">
<root>
<menuitem label="Edit">
<menuitem label="Frame Selection" keyEquivalent="f"/>
</menuitem>
</root>
</fx:XML>
</fx:Declarations>
This works great, but when I try to type text in any textfield or textInput
anywhere in the app, I cant ever type f.
How can stop the menu from stealing my keyboard input ?
Perhaps a better pattern to menu accelerators would use the control key, such as CTRL+F in your example.
Your menuitem would therefore include controlKey="true"
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:menu>
<mx:FlexNativeMenu id="mainMenu"
dataProvider="{menuData}"
labelField="#label"
keyEquivalentField="#keyEquivalent"
showRoot="false" />
</s:menu>
<fx:Declarations>
<fx:XML format="e4x"
id="menuData">
<root>
<menuitem label="Edit">
<menuitem label="Frame Selection"
keyEquivalent="f"
controlKey="true" />
</menuitem>
</root>
</fx:XML>
</fx:Declarations>
<s:TextInput />
</s:WindowedApplication>
I am using a combobox for the us states, link. The label is set to the full name of the state, while the value attribute holds the abbreviation. What I want to do is to get the selected item's value. So I tried combo.selectedItem.value and combo.selectedItem.#value, but neither of them worked. Can someone shed a light on this please?
Here's a simple example that might be helpful.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:ComboBox id="comboBox" dataProvider="{[{label:'California', value:'CA'}, {label:'New York', value:'NY'}]}" />
<mx:Label text="{comboBox.selectedItem.value}" />
</mx:Application>
Here's another example. In this one we use XML as dataProvider.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:XML id="xml" xmlns="">
<states>
<state label="Alabama" value="AL" country="US" />
<state label="Alaska" value="AK" country="US" />
<state label="Arkansas" value="AR" country="US" />
</states>
</mx:XML>
<mx:ComboBox id="comboBox" dataProvider="{xml.state}" labelField="#label" />
<mx:Label text="{comboBox.selectedItem.#value}" />
</mx:Application>
You can populate an array with the values you want to get and retrieve the index of the selected item on the combo box (which should be the same as in the array).
Or in your component ... just look for the index (selected item) child on statesUS