Required fields in flex - apache-flex

I've got a question about flex.
I have a form and the email is required.
I googled this and found the following solution:
<mx:FormItem label="Email" id="emailFormItem" width="100%" styleName="formEven" required="true">
<mx:TextInput id="emailTextInput" width="100%" text="{user.email}"/></mx:FormItem>
The problem is that when I press ok the call is still made.
I know you have to validate the following by yourself but does anyone has an idea how I can validate the field(s)?
Solution:
I've found a solution for this:
You can create a validator for each field you want to validate and then create this function:
private function isValid():Boolean {
var failedValidators:Array = Validator.validateAll([emailValidator, userNameValidator, languageValidator, firstNameValidator, lastNameValidator]);
return failedValidators.length == 0;
}
This can be closed.

what I generally do is create a method called something like isSubmitEnabled or isFormComplete. I call it on keyUp on every field that is required and check for values in all of the fields (and any other validation I want to do) and then as long as everything checks out I set the submit button to be enabled otherwise I set the submit button to be disabled. As long as you disable the button when you start then you should be good to go.
I have used this method several times and find it to be the easiest to use and especially to maintain. I will look at the docs and see if I can see what you can do with the required attribute on the form item though.
Update:
According to the docs:
This property controls the indicator
display only. You must attach a
validator to the children if you
require input validation.
What you want is mx.validators.Validator (http://livedocs.adobe.com/flex/3/langref/mx/validators/Validator.html)
<mx:Validator id="reqValid" required="true"
source="{fname}" property="text"
valid="handleValid(event)" invalid="handleValid(event)"/>
See the code examples on that link to see how to use it. The example is actually exactly what you are looking for I think. HTH

<fx:Declarations>
<mx:RadioButtonGroup id="a1" itemClick="usdradio(event);"/>
<fx:Model id="creditcard">
<card>
<cardType>{cardTypeCombo.selectedItem.data}</cardType>
<cardNumber>{cardNumberInput.text}</cardNumber>
</card>
</fx:Model>
<mx:CreditCardValidator id="ccV"
cardTypeSource="{creditcard}" cardTypeProperty="cardType"
cardNumberSource="{creditcard}" cardNumberProperty="cardNumber"
trigger="{myButton}" triggerEvent="click"
cardTypeListener="{cardTypeCombo}"
cardNumberListener="{cardNumberInput}"
valid="Alert.show('Validation Succeeded!')"/>
<mx:ArrayCollection id="dp">
<fx:Object label="American Express" data="American Express"/>
<fx:Object label="Diners Club" data="Diners Club"/>
<fx:Object label="Discover" data="Discover"/>
<fx:Object label="MasterCard" data="MasterCard"/>
<fx:Object label="Visa" data="Visa"/>
</mx:ArrayCollection>
<mx:CurrencyValidator source="{priceUS}" property="text" precision="2"
trigger="{myButton2}" triggerEvent="click"
valid="Alert.show('Validation Succeeded!')"/>

Related

How to pass column value to dataTipFunction in AdvancedDataGridColumn Flex

Flex Experts,
I am a newbie here. I am trying to create a conditional tool tip for my contact detail screen. If the contact has 'special-roles' like 'ABC, XYZ' then the tool tip should appear otherwise not. We have AdvancedDataGridColumn and using dataTipFunction to display the tool tip.
I am passing, values of roles & 'special-roles' in dataProvider for all contact objects.
I need to write tool-tip condition for every row(every contact). I am unable to write the condition in dataTipFunction as it has access to only 'item' object. I tried trace and Alert on 'item', but screen goes blank.
I have also tried "showDataTips" which accepts boolean but to no avail. I need a way to pass current row values (all columns) to a function from AdvancedDataGridColumn.
Here is the snapshot of my code. Any help is very much appreciated :)
<view:CopyPasteDataGrid id="contactsHolder"
width="100%"
height="100%"
displayDisclosureIcon="true"
variableRowHeight="true"
defaultLeafIcon="{null}"
folderClosedIcon="{null}"
folderOpenIcon="{null}"
useRollOver="true"
selectable="true"
styleName="PortfolioAdvanced"
designViewDataType="tree"
horizontalCenter="true"
verticalGridLines="false"
horizontalScrollPolicy="off"
dataProvider="{contactDetails}"
headerRelease="onHeaderRelease(event)">
<view:columns>
<mx:AdvancedDataGridColumn dataField="lastName"
sortCompareFunction="lastNameCompare"
headerText="{ApplicationConstants.LAST_NAME_HEADER}"
showDataTips="true" dataTipFunction="buildToolTipForContact"
width="100"/>
<view:rendererProviders>
<mx:AdvancedDataGridRendererProvider dataField="projectContacts"
renderer="com.ihg.hom.common.view.components.render.ContactsRenderer"
columnIndex="0"
columnSpan="0"/>
</view:rendererProviders>
</view:CopyPasteDataGrid>
private function buildToolTipForContact(item:Object):String
{
var myString:String="";
return "hello";
}
I have resolved it using different approach. I used label function. It has access to column object and based current object roles I am setting tool tip. Here is the code for reference.
<mx:AdvancedDataGridColumn dataField="role" sortable="{isRoleSortable}"
labelFunction="getRole"
headerText="Role" sortCompareFunction="sortRole" showDataTips="true" dataTipFunction="buildToolTipForContact"
width="120"/>
private var hasRole:Boolean=false;
private function getRole(item:Object):String
{
// extra code
if(currentRoles.indexOf(specialRole)!=-1)
{
hasRole=true;
}
}
private function buildToolTipForContact(item:Object):String
{
var myStr:String="";
if(hasRole){
myStr="Special Role";
}
return myStr;
}

Flex DateField / DateChooser Issue

We use the mx:DateField for our Dates and editable="true" so that we can either choose a date or enter it as well. The requirement is that we should not be able to enter more than 10 characters in this field (10/10/2010). But the DateField does not have the maxChars property to restrict that.
So we tried to use a Text Field + DateChooser to restrict the number of characters. Everything works as desired, but the issue is that the DateChooser shows the whole calendar on the page and not as a Calendar icon that will popup a calendar (as DateField).
So now my q is
1) Using the DateField, how can I restrict the number of characters that can be entered in the text field to 10
or
2) Using the DateChooser, how can I change the appearance of it to show a Calendar Icon and then show the calendar as popup on clicking it (similar to DateField).
If anyone can help me on this, that would be wonderful.
Start with something like this:
<s:TextInput click="dc.visible=!dc.visible" maxChars="10" />
<mx:DateChooser id="dc" visible="false" />
From here you just need to handle click events to the date chooser and fill out the textinput appropriately
UPDATE:
In attempt to answer your questions from comments
UI:
<s:HGroup>
<s:TextInput id="dateInput" click="dateInput_clickHandler(event)" maxChars="10" />
<mx:DateChooser id="dc" visible="false" includeInLayout="false" change="dc_changeHandler(event)" />
</s:HGroup>
Script:
protected function dateInput_clickHandler(event:MouseEvent):void
{
dc.includeInLayout = !dc.includeInLayout;
dc.visible = !dc.visible;
}
protected function dc_changeHandler(event:CalendarLayoutChangeEvent):void
{
dateInput.text = dateFormatter.format(event.newDate);
dateInput_clickHandler(null);
}
Declarations:
<mx:DateFormatter id="dateFormatter" formatString="MM/DD/YYYY" />
Hope this helps!
-Ian

Flex : Adding a click handler on SkinnableDataContainer's items

I am new to Flex.
What I am looking for here is adding a click handler on all the items created by a SkinnableDataContainer. I tried several things that didn't work, and I have no idea what is the right way to do it.
<s:SkinnableDataContainer id="teamList"
itemRenderer="TeamSummaryRenderer">
<s:dataProvider>
<s:ArrayList>
<fx:Object teamName="A super team 1"/>
<fx:Object teamName="A super team 2"/>
<fx:Object teamName="A super team 3"/>
</s:ArrayList>
</s:dataProvider>
</s:SkinnableDataContainer>
Furthermore, I don't want to declare the handler in my custom TeamSummaryRenderer component. I would prefer that the handler code stays at application level.
Is there a simple 'Flex-ish' to achieve this ?
No.
<s:SkinnableDataContainer
Properties
autoLayout="true"
clipAndEnableScrolling="false"
dataProvider="null"
horizontalScrollPosition="null"
itemRenderer="null"
itemRendererFunction="null"
layout="VerticalLayout"
typicalItem="null"
verticalScrollPosition="null"
Events
rendererAdd="No default"
rendererRemove="No default"
/>
http://opensource.adobe.com/wiki/display/flexsdk/Spark+SkinnableDataContainer
I think you have to keep your handler in the itemRenderer as the document says. They don't have any properties to achieve it directly.
Ok ... I found the answer myself :
<s:SkinnableDataContainer
rendererAdd="my_handler(event)"/>
private function my_handler(event:RendererExistenceEvent):void{
event.renderer.addEventListener(flash.events.MouseEvent.CLICK, clickhandler);
}
The rendererAdd event is triggered every time a new renderer is added to the container, and it has a property renderer which is the renderer object itself. So here is the place for adding a click handler on every one of the renderers that are created.
You could also subclass the SkinnableDataContainer and handle all the renderer-listening there. Then, when your eventhandler is triggered, your custom SkinnableDataContainer will dispatch a change event or some other event. Next, in your application, you set a listener on that specific event and there you go...

detect change in Flex Form elements (textinput, textarea, combobox, checkbox..)

I have various (read lots of..) flex forms in my app, and I now want to create a system by which the user is notified that he hasn't saved if he modifies anything in the form...
now.. I don't want to rewrite every form I have.. is there some nice way to implement this?
Extending the TextInput (and others..) classes somehow?
thanks
This is not really thought through but should work.
You could create a custom component, let's call it FormWatcher which you would than put next to your Form. What the form watcher would do is wait for the CreationComplete event from the form.
So now, as we have the Form ready you can use the getChildren() method of the form to get all the FormItems in it. Than look inside each of them, and you will get TextInputs, Comboboxes, etc. to which you can add event listeners (as individual components), eg.
// THIS IS WHERE THE COMPONENT SHOULD START
protected function changeHandler(event:Event):void
{
trace ("something is dirty");
}
protected function startWatching(passTheFormHere:Form):void
{
for each (var O:Object in passTheFormHere.getChildren())
{
if (O is FormItem)
{
// Let's assume you only have a single child in one FormItem
// and always one child for simplicity
addChangeHandlerFor((O as FormItem).getChildAt(0));
}
}
}
protected function addChangeHandlerFor(someComponent:Object):void
{
// Most regular flex components send a Event.CHANGE event
// when their value is changing
// keep in mind you should check stuff, this is a simple example
(someComponent).addEventListener(Event.CHANGE,changeHandler);
}
// THIS IS WHERE THE COMPONENT SHOULD END
Just paste this code next to some form, and call the startWatching(nameOfYourForm), you should see the changeHandler is being called.
A few more notes:
1) You should clean up the event listeners once you're done.
2) I would create a component out of it so that you would use it like this:
<mx:Form id="form1" >
[...]
</mx:Form>
<FormWatcher form="{form1}" />
Where FormWatcher would have a Boolean var called "clean" or something.
3) The example is very simple, so it will only work for forms similiar to this one:
<mx:Form id="myForm" >
<mx:FormItem>
<mx:TextInput id="someComponent1" />
</mx:FormItem>
<mx:FormItem>
<mx:CheckBox id="someComponent2" />
</mx:FormItem>
<mx:FormItem>
<mx:TextArea id="someComponent3" />
</mx:FormItem>
</mx:Form>
You could go into the TextInput class (and others) and add that event listener and function, but then you would be changing the SDK itself, which is kind of a bad idea. I would create custom classes extending the ones your using and do a find/replace to make it faster.

Preventing validator from firing after bound value changes

I am working on a product options form whose contents should be cleared by a clearOptions() method each time the user adds an option. The option name TextInput is bound to a value object that is reinstantiated each time the the user adds a product option. The problem I am having is that the StringValidator fires each time the bound value object is reinstantiated.
<mx:StringValidator id="valOptionName" minLength="1" source="{txtOptionName}" property="text" trigger="{btnAddChangeOption}" triggerEvent="click"/>
<mx:TextInput id="txtOptionName" width="120" text="{currentProductOption.name}"/>
<mx:LinkButton id="btnAddChangeOption" label="Add/Change Option" click="saveUpdateOption(event)" horizontalCenter="0"/>
The following code is what causes the StringValidator to fire when it shouldn't. It results in a red outline around a text box.
private function clearOptions():void
{
currentProductOption = new ProductOptionVO();
}
Thank you for any help,
Orville
I solved the problem by setting the source of the validator manually in the validation code and then switching it off before currentProductOption is reinstantiated.

Resources