flex: how to validating multiple required fields - apache-flex

I can validating only one filed.
<mx:Validator required="true" property="text" source="{name}" valid="vaildator(event)" invalid="vaildator(event)" />
thanks

Use Validator.validateAll() function to get the validity of each field and then check if the returned array is empty.
<?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>
<mx:StringValidator
id="svSurname"
source="{tiSurname}"
property="text"
requiredFieldError="Surname is required!"
required="true"/>
<mx:StringValidator
id="svFirstname"
source="{tiFirstname}"
property="text"
requiredFieldError="Firstname is required!"
required="true"/>
<mx:NumberValidator
id="nvAge"
source="{tiAge}"
property="text"
lowerThanMinError="Only after 18 years old"
minValue="18"
requiredFieldError="Age is required!"
required="true"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.validators.Validator;
private function onBtnEnter():void
{
var validationResult:Array = Validator.validateAll([svSurname, svFirstname, nvAge]);
if (validationResult.length == 0)
Alert.show("All right!");
else
Alert.show("You have an error!");
}
]]>
</fx:Script>
<s:VGroup x="10" y="10" width="250" height="150">
<s:HGroup width="100%" verticalAlign="bottom">
<s:Label text="Surname*" width="120" textAlign="right"/>
<s:TextInput id="tiSurname" width="120"/>
</s:HGroup>
<s:HGroup width="100%" verticalAlign="bottom">
<s:Label text="Firstname*" width="120" textAlign="right"/>
<s:TextInput id="tiFirstname" width="120"/>
</s:HGroup>
<s:HGroup width="100%" verticalAlign="bottom">
<s:Label text="Age*" width="120" textAlign="right"/>
<s:TextInput id="tiAge" width="120"/>
</s:HGroup>
<s:HGroup horizontalAlign="center" width="100%" height="40">
<s:Button id="btnEnter" label="Send" click="onBtnEnter()"/>
</s:HGroup>
</s:VGroup>
</s:Application>

Related

adobe flex user input must contain a "/" character

In my project I have an user input, the first 4 characters should be number, and the fifth character must be /, is there a way to control this?
I am using Adobe Flash builder 4.6. I only know use restrict for number input.
EDIT1:
After following Timofei's solution, I modified my source code as followings, but it not take effect, only notifying user "This field is required". Whatever I input in the textbox, no warning there, is it some wrong with my code?
<?xml version="1.0" encoding="utf-8"?>
<viewer:BaseWidget xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:viewer="com.esri.viewer.*"
right="450" bottom="175" width="320" height="450" widgetConfigLoaded="init()">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import spark.events.IndexChangeEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import mx.managers.PopUpManager;
public function handleEvent():void
{
mx.controls.Alert.show("bq no input: " + attr_bqNo.text)
}
]]>
</fx:Script>
<fx:Declarations>
<mx:RegExpValidator id="validator" expression="^\d\{4\}/" noMatchError="Error text here" source="{attr_bqNo}" property="text"
trigger="{attr_bqNo}" triggerEvent="change"/>
</fx:Declarations>
<s:TextInput id="attr_bqNo" x="41" y="29" width="212"/>
<viewer:WidgetTemplate id="attributesearch"
width="320" height="450">
<viewer:layout>
<s:BasicLayout/>
</viewer:layout>
<s:Label x="41" y="15" width="132" height="15" text="BQ No."/>
<s:Label x="40" y="59" width="150" height="16" text="Contract No."/>
<s:TextInput id="attr_contractNo" x="41" y="73" width="213"/>
<s:Label x="40" y="146" text="Drain Name"/>
<s:TextInput id="attr_drainName" x="40" y="159" width="213"/>
<s:Label x="40" y="189" text="Project/Contract Title"/>
<s:TextInput id="attr_projectTitle" x="40" y="203" width="213"/>
<s:Label x="40" y="323" text="Location (Road Name)"/>
<s:TextInput id="attr_roadName" x="40" y="337" width="213"/>
<s:Button id="attr_ok" x="68" y="367" label="Ok" click = "handleEvent()"/>
<s:Button id="attr_clear" x="156" y="367" label="Clear"/>
</viewer:WidgetTemplate>
</viewer:BaseWidget>
You can use RegExpValidator.
<fx:Declarations>
<mx:RegExpValidator id="validator" expression="^\d\{4\}/" noMatchError="Error text here" source="{input}" property="text"
trigger="{input}" triggerEvent="change"/>
</fx:Declarations>
<s:TextInput id="input"/>
Read about validators

How to enable vertical scroll in a flex mobile View?

At runtime when I click the Lire button then the TextArea field under it is populated from a sharedobject data and the display becomes bigger :
Here is code :
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark" title=""
creationComplete="creationCompleteHandler(event)" >
...
<s:VGroup width="100%" height="100%" paddingTop="5" verticalAlign="middle" horizontalAlign="center">
<s:TextInput id="chp1" width="50%"/>
<s:TextInput id="chp2" width="50%"/>
<s:Button label="Enregistrer" click="enregistrer(event)" />
<s:Label/>
<s:Button label="Lire" click="lire(event)" />
<s:TextArea id="area"/>
<s:Label/>
<s:HGroup>
<s:Button label="Envoyer" click="send(event)" />
<s:Button label="Retour" click="navigator.popView()" />
</s:HGroup>
<s:TextArea id="resultHTTP"/>
<s:TextInput id="h_url" text="{url}" visible="false"/>
</s:VGroup>
How to enable vertical scroll then to view others components at the bottom ?
wrap your VGroup with a scroller. something like this:
's:Scroller width="100%" height="100%"
s:VGroup width="100%" height="100%" paddingTop="5" verticalAlign="middle" horizontalAlign="center"'

refresh the itemrenderer of each item in the List component Flex

I have the list shown below:
<s:List id="list2" width="100%" height="100%" dataProvider="{ recordingsShown }"
itemRenderer="components.VideoItemRenderer2"
selectedIndex="0" visible="false">
<s:layout>
<s:TileLayout id="tilelayout"
useVirtualLayout="true"
orientation="columns"
columnAlign="justifyUsingWidth" rowAlign="justifyUsingHeight"
requestedColumnCount="3"
requestedRowCount="2"
paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"
verticalGap="10" horizontalGap="10" />
</s:layout>
</s:List>
which displays in tiles a name, a date and a preview image for each one of the videos contained in the arraycollection recordingsShown given as dataprovider.
The problem is when a new video is added,i save the preview pic in a folder and a node describing it in an xml and i put a new item in the arraycollection with
recordingsShown.addItemAt(newRecording,0);
it is added on stage but the preview image of the last added video is not shown!
How can i redraw the whole list in order to show it?
Here is my itemRenderer:
<?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"
width="400" height="300" autoDrawBackground="true">
<fx:Metadata>
[Event(name="playClicked", type="flash.events.Event")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import flash.filters.GlowFilter;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.formatters.DateFormatter;
protected function img_rollOverHandler(evt:MouseEvent):void {
Image(evt.currentTarget).filters = [new GlowFilter(0xf7941d)];
Image(evt.currentTarget).alpha = 0.9;
}
protected function img1_rollOutHandler(evt:MouseEvent):void {
Image(evt.currentTarget).filters = [];
Image(evt.currentTarget).alpha = 1;
}
protected function playClickHandler(event:MouseEvent):void
{
dispatchEvent(new Event("playClicked",true,true));
}
]]>
</fx:Script>
<fx:Declarations>
<s:DateTimeFormatter id="dateTimeFormatter"
dateTimePattern="DD.MM.YYYY HH.NN.SS"/>
</fx:Declarations>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="selected" />
</s:states>
<s:Rect width="100%" height="100%" radiusX="5" radiusY="5">
<s:filters>
<s:DropShadowFilter alpha="0.32" alpha.hovered="0.5" blurX="5" blurY="5" distance="2" />
</s:filters>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0x323232" color.selected="black"/>
<s:GradientEntry color="#7f7f7f" color.selected="0x333333"/>
</s:LinearGradient>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#ffffff" color.hovered="#f7941d" color.selected="#ed7f09" caps="none" weight="2" joints="miter" miterLimit="4"/>
</s:stroke>
</s:Rect>
<s:Label left="10" top="10"
fontStyle="italic"
fontWeight="bold"
color="#f7941d"
text="{dateTimeFormatter.format(data.date)}"/>
<s:Label left="10" top="25"
fontSize="16"
fontWeight="bold"
color="#ffffff"
text="{data.name}"/>
<s:Image id="previewImg" left="10" right="10" bottom="10" top="55" scaleMode="stretch" smooth="true"
source="http://localhost:5080/thumbs/{data.thumb}" />
<!-- source="assets/img.jpg"/> -->
<s:Image source="assets/play.png"
rollOver="img_rollOverHandler(event);"
rollOut="img1_rollOutHandler(event);"
x="136" y="102"
click="playClickHandler(event)"
complete="this.invalidateSize()"/>
</s:ItemRenderer>
I have found that there seems to be a problem with data binding and the Spark Image. Try adding this to the root tag:
dataChange="yourImage.validateNow();
If that doesn't work, set the whole path in dataChange.

Set dataprovider of buttonbar component

I am trying to add a navigation component with a button bar in it that controls the view stack of the main application. Here is what I have so far for the main application's code:
<?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"
xmlns:comps="comps.*" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
public var myViewStack:ViewStack;;
]]>
</fx:Script>
<fx:Binding source="lgViewStack" destination="myViewStack"/>
<comps:viewControl id="myControl" width="935" horizontalCenter="0" top="5" height="134"/>
<mx:ViewStack id="lgViewStack" width="935" height="474" left="10" verticalCenter="66">
<s:NavigatorContent label="View 1" width="100%" height="100%" id="view1">
<s:Panel id="firstPanel" title="First Panel" width="250" height="200" horizontalCenter="0" verticalCenter="0" >
</s:Panel>
</s:NavigatorContent>
<s:NavigatorContent label="View 2" width="100%" height="100%" id="view2">
<s:Panel id="secondView" title="Second View" width="250" height="200" horizontalCenter="0" verticalCenter="0" >
</s:Panel>
</s:NavigatorContent>
</mx:ViewStack>
</s:Application>
And the component code:
<?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" width="400" height="300">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:ButtonBar x="170" y="10" width="58" dataProvider="{myViewStack}"/>
</s:Group>
I receive a compile error from the component: Access of undefined property myViewStack. Am I referencing the variable myViewStack incorrectly? I am still trying to understand how bindings work.
ViewControl
<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:Script>
<![CDATA[
public function set dataProvider(value:ViewStack):void
{
bar.dataProvider = value;
}
public function get dataProvider():ViewStack
{
return bar.dataProvider;
}
]]>
</fx:Script>
<s:ButtonBar id="bar"/>
</s:Group>
Main
<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"
xmlns:comps="comps.*">
<comps:ViewControl dataProvider="{viewstack}"/>
<mx:ViewStack id="viewstack" />
</s:Application>
Should also be noted that you could always just extend ButtonBar in your custom component instead depending what you're trying to accomplish by creating that component.
You should move public var myViewstack:ViewStack field declaration into your component. Think about MXML components as ordinary classes according with OOP conceptions. So for your code:
<?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"
xmlns:comps="comps.*" minWidth="955" minHeight="600">
<comps:viewControl id="myControl" width="935" horizontalCenter="0" top="5" height="134" myViewstack="{lgViewStack}" />
<mx:ViewStack id="lgViewStack" width="935" height="474" left="10" verticalCenter="66">
<s:NavigatorContent label="View 1" width="100%" height="100%" id="view1">
<s:Panel id="firstPanel" title="First Panel" width="250" height="200" horizontalCenter="0" verticalCenter="0" >
<s:Label id="testSource" text="Text to copy" />
</s:Panel>
</s:NavigatorContent>
<s:NavigatorContent label="View 2" width="100%" height="100%" id="view2">
<s:Panel id="secondView" title="Second View" width="250" height="200" horizontalCenter="0" verticalCenter="0" >
</s:Panel>
</s:NavigatorContent>
</mx:ViewStack>
</s:Application>
and
<?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" width="400" height="300">
<fx:Script>
<![CDATA[
[Bindable]
public var myViewstack:ViewStack;
]]>
</fx:Script>
<s:ButtonBar x="170" y="10" width="58" dataProvider="{myViewStack}"/>
</s:Group>

flex 4 tabbar - disable tab

is there a common way to disable a tab of a spark tabbar component in flex 4? with the mx tabnavigator component you can just disable the content corresponding to the tab and the tab is also disabled then. but doing this with the spark tab bar component disables just the content not the tab.
here is my simple example:
<mx:TabNavigator x="122" y="155" width="200" height="200">
<s:NavigatorContent label="Tab 1" width="100%" height="100%">
<s:Label text="Label1"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 2" width="100%" height="100%" enabled="false">
<s:Label text="Label2"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 3" width="100%" height="100%">
</s:NavigatorContent>
</mx:TabNavigator>
<s:TabBar x="368.7" y="100.35" dataProvider="{viewstack1}" />
<mx:ViewStack x="364" y="133" id="viewstack1" width="200" height="200">
<s:NavigatorContent label="Tab 1" width="100%" height="100%">
<s:Label text="Label1"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 2" width="100%" height="100%" enabled="false">
<s:Label text="Label2"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 3" width="100%" height="100%">
<s:Label text="Label3" x="1" y="0"/>
</s:NavigatorContent>
</mx:ViewStack>
many thx,
florian
Addendum:
Literally two minutes after I got back to actually working, I found an "elegant" solution using a skin.
If you apply a custom skinClass to your tab bar you can bind the tab.enabled property just like you'd expect/want.
<fx:Script>
<![CDATA[
[Bindable] private var tab2IsReady:Boolean = false;
private function checkCriteria():void{
tab2IsReady = someOtherThing.isFinished;//Boolean
}
]]>
</fx:Script>
<s:TabBar id="theTabBar"
dataProvider="{viewStack}"
skinClass="skins.CustomTabBarSkin"/>
<mx:ViewStack id="viewStack">
<s:NavigatorContent label="Tab index 0">
<!-- Your first tab's content -->
</s:NavigatorContent>
<s:NavigatorContent label="Tab index 1" enabled="{tab2IsReady}">
<!-- Your second tab's content -->
</s:NavigatorContent>
</mx:ViewStack>
When you type "skinClass" use the auto complete to generate (in FlashBuilder ~4.5+???) the custom skin (named whatever you want).
The code will appear like below (I left out the Script tag).
<?xml version="1.0" encoding="utf-8"?>
<!-- skins/CustomTabBarSkin.mxml
...
Adobe's copyright & doc comments
...
-->
<s:Skin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.TabBar")]
]]>
</fx:Metadata>
<!-- optional Script tag here -->
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<!--- #copy spark.components.SkinnableDataContainer#dataGroup -->
<s:DataGroup id="dataGroup" width="100%" height="100%">
<s:layout>
<s:ButtonBarHorizontalLayout gap="-1"/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
</s:Skin>
<!-- End skins/CustomTabBarSkin.mxml -->
Change:
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
</fx:Component>
To:
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin"
enabled="{data.enabled}" />
</fx:Component>
Then any <s:NavigatorContent/> in the ViewStack with its enabled property set or bound will do exactly what you expect
(be enabled when true, & disabled when false).
One solution to try would be to use mx:VBox components instead of s:NavigatorContent.
From http://blog.flexexamples.com/2007/08/25/enabling-and-disabling-specific-tabs-in-a-tabbar-control/ :
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/25/enabling-and-disabling-specific-tabs-in-a-tabbar-control/ -->
<mx:Application name="TabBar_enabled_test"
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:ApplicationControlBar dock="true">
<mx:CheckBox id="tabBarEnabled"
label="TabBar.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab1Enabled"
label="Tab1.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab2Enabled"
label="Tab2.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab3Enabled"
label="Tab3.enabled"
selected="true"
width="25%" />
</mx:ApplicationControlBar>
<mx:VBox verticalGap="0">
<mx:TabBar id="tabBar"
width="400"
dataProvider="{viewStack}"
enabled="{tabBarEnabled.selected}" />
<mx:ViewStack id="viewStack" width="400" height="100">
<mx:VBox id="tab1"
label="Tab1"
backgroundColor="haloGreen"
enabled="{tab1Enabled.selected}">
<mx:Label text="Label 1" />
</mx:VBox>
<mx:VBox id="tab2"
label="Tab2"
backgroundColor="haloBlue"
enabled="{tab2Enabled.selected}">
<mx:Label text="Label 2" />
</mx:VBox>
<mx:VBox id="tab3"
label="Tab3"
backgroundColor="haloOrange"
enabled="{tab3Enabled.selected}">
<mx:Label text="Label 3" />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:Application>
For those who want an working answer for Flex 4.5 (probably Flex 4 also). I finally figured out a solution. It feels like a hack to me, but Adobe's not answering the call and it's working for me. Here's a simplified example.
<!-- component that has the the TabBar in it... -->
<fx:Script>
<![CDATA[
//imports here
import mx.core.UIComponent;
//imports
private function setTabEnabled(index:int,enabled:Boolean):void{
var theTab:UIComponent = theTabBar.dataGroup.getElementAt(index) as UIComponent;
if(theTab){theTab.enabled = enabled;}
}
]]>
</fx:Script>
<s:TabBar id="theTabBar"
dataProvider="{viewStack}"/>
<mx:ViewStack id="viewStack">
<s:NavigatorContent label="0th Tab">
<!-- ...Content -->
</s:NavigatorContent>
<s:NavigatorContent label="1st Tab">
<!-- ...Content -->
</s:NavigatorContent>
<s:NavigatorContent label="2nd Tab">
<!-- ...Content -->
</s:NavigatorContent>
</mx:ViewStack>
<!-- rest of the component that has the the TabBar in it... -->
Then you just call setTabEnabled(theTabIndex,trueFalse) in an event handler related to whatever decides why the tab is, or isn't, enabled.
I should extend the TabBar to support this, but I've already spent enough time trying to figure it out.
Happy Coding =D

Resources