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
Related
I am trying to make flex autocomplete change its dataprovider at runtime based on user input.
<components:AutoComplete change="change()" id="ac" dataProvider="{_a1}" width="100" />
<s:Button label="change" click="change()" />
private function change():void
{
Alert.show("sdsd");
//Alert.show(event.text);
//ac.dataProvider = _a2;
}
when I click the button, the function get fired, but when i input the text, it doesnt fire.
I was trying to use both change and textEvent, however, none of them are fired.
I wonder if there is any way that i can do this?
Thanks in advance.
I inserted a dateField component. On clicking, it displays calendar. I would like to add 2 comboboxes, one shows hours (0 to 23) and other for minutes (0 to 59), to the calendar so that the user can select the time along with the date, and that will be displayed in the text input as date and time. One more thing I would like to add is clear button to clear the selected date in the calendar.
Since a DateField is essentially a TextInput coupled with a DateChooser, why not do that yourself? Also add your two ComboBox, make your TextInput editable="false" text="{dateTime}" where dateTime is a Bindable string variable you create as the concatenation of the values in the DateChooser and the two ComboBox. Call the function that creates the dateTime string on the change event of all three inputs.
Finally, add your clear Button, and have its click event call a function where you set the DateChooser to today, and the two combo boxes to default values, and update dateTime string as needed (to blank or to current date/time depending on what you are trying to do.)
Edit:
As you asked nicely, and as I am studying for the ACE exam and thought this made a nice excercise, here is what I came up with. I made the following custom component in a package named 'components' and called it 'myCustomDateField.mxml'
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="resetDisplay()">
<mx:DateFormatter id="dateFormat" formatString="DD-MMM-YYYY JJ:NN" />
<mx:Script>
<![CDATA[
[Bindable]
public var dateTime:Date;
private function updateDisplay():void {
var userDate:Date = new Date();
userDate.date = cal.selectedDate.date;
userDate.month = cal.selectedDate.month;
userDate.fullYear = cal.selectedDate.fullYear;
userDate.hours = hour.value;
userDate.minutes = minute.value;
dateTime = userDate;
}
private function resetDisplay():void {
var now:Date = new Date();
cal.selectedDate = now;
hour.value = now.hours;
minute.value = now.minutes;
dateTime = now;
}
]]>
</mx:Script>
<mx:Label text="Select Date and Time:" />
<mx:TextInput id="display" text="{dateFormat.format(dateTime)}" editable="false" />
<mx:DateChooser id="cal" yearNavigationEnabled="true" change="updateDisplay()" />
<mx:Label text="Hour:" />
<mx:NumericStepper id="hour" minimum="0" maximum="23" change="updateDisplay()" />
<mx:Label text="Minute:" />
<mx:NumericStepper id="minute" minimum="0" maximum="59" change="updateDisplay()" />
<mx:Button label="Clear" click="resetDisplay()" />
</mx:HBox>
In my application, I added the xmlns:cust="components.*" in the declaration tag, and inserted one <cust:myCustomDateFeild id="myDate" />. I was able to access the entry in the parent by using {myDate.dateTime}.
I made a few design assumption that you may decide to change, like the formatter, and I replaced your combo boxes with NumericStepper.
I have an ArrayCollection bound to an editable DataGrid, another component needs to know when the ArrayCollection changes (as a result of changes in the DataGrid) so it can also update itself, so is listening to the COLLECTION_CHANGE event of the ArrayCollection.
The problem is that the DataGrid only updates the ArrayCollection when the row being edited losses focus. This is not good for my app as a user could edit a column on a row and not click elsewhere on the table for a long time (causing the row to lose fucus), therefore the changes won't have propagated to the other parts of the application.
How can I make the data grid inform the ArrayCollection of a change every time there is a keyup event on a text input instead of every time a row looses focus?
Cheers,
Chris
I would add the handler to the component used to edit the value instead of to the ArrayCollection. Example:
<mx:DataGridColumn dataField="name" headerText="Name" itemEditor="{nameEditor}" editorDataField="selectedItem" />
Then this is used to edit the value:
<mx:Component id="nameEditor">
<mx:ComboBox dataProvider="{outerDocument.names}" change="outerDocument.setNameField(event)" close="outerDocument.setNameField(event)" />
</mx:Component>
And this is the handler for the change (and close) event:
public function setDestinationField(event:*):void {
var destination:String = (event.target as ComboBox).selectedLabel;
if (destination === '') {
delete _gridData[_currentlyEditedRowIndex].destination;
} else {
_gridData[_currentlyEditedRowIndex].destination = destination;
}
}
_currentlyEditedRowIndex is set by adding this to the grid:
itemEditBegin="beginEdit(event);"
Thanks Gabriel you put me on the right path. I will post here my final solution in case anyone else needs to do the same thing in the future.
<mx:DataGridColumn headerText="Title" width="300" dataField="title">
<mx:itemEditor>
<mx:Component>
<mx:TextInput change="data.title = text" />
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
Now whenever the text is changed in the input the ArrayCollection being used as the data provider is also updated, so other components listen for COLLECTION_CHANGE events.
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.
Say I have a phone-number validator in flex and I have two TextInput controls for phone numbers. I don't want to have two separate validator controls defined that have essentially the same attributes... but each validator has only one "source" attribute. How can I use the same validator on multiple control? (or any equivalent solution)
Not inline, but you can perform the validation programmatically, say, on submission of a form, or when a user tabs out of a control, etc. Here's an example using a single PhoneNumberValidator to validate two form fields; the validation happens when the Submit button gets clicked:
<mx:Script>
<![CDATA[
private function validatePhoneNumber(txt:TextInput):void
{
v.listener = txt;
v.validate(txt.text);
}
private function btn_click():void
{
validatePhoneNumber(p1);
validatePhoneNumber(p2);
}
]]>
</mx:Script>
<mx:PhoneNumberValidator id="v" allowedFormatChars="()- .+" property="text" requiredFieldError="Required." wrongLengthError="Invalid length." invalidCharError="Invalid character." />
<mx:Form>
<mx:FormItem label="Phone Number 1">
<mx:TextInput id="p1" />
</mx:FormItem>
<mx:FormItem label="Phone Number 2">
<mx:TextInput id="p2" />
</mx:FormItem>
<mx:FormItem>
<mx:Button id="btn" label="Submit" click="btn_click()" />
</mx:FormItem>
</mx:Form>
Hope it helps!
Steps to reproduce:
TextInput creates dynamically
textInputBox = new MyTextInput;
textInputBox.restrict = “0-9.”;
textInputBox.maxChars = 24;
amountValidator = new NumberValidator();
amountValidator.source = textInputBox;
amountValidator.property = “text”;
amountValidator.allowNegative = false;
amountValidator.domain = “real”;
amountValidator.precision = 4;
amountValidator.required = false;
amountValidator.maxValue = 999999999999.9999;
amountValidator.trigger = textInputBox;
amountValidator.triggerEvent = Event.CHANGE;
amountValidator.addEventListener(ValidationResultEvent.VALID, amountValid);
amountValidator.addEventListener(ValidationResultEvent.INVALID, amountInvalid);
private function amountValid(event:ValidationResultEvent):void
{
valid = true;
fieldsValidated = true;
}
private function amountInvalid(event:ValidationResultEvent):void
{
valid = false;
fieldsValidated = true;
}
As mention in the creation, when we exceed the limit, it shows error my red color border, and the same time if you delete them by DEL key when it come to the given acceptable limit, automatically become to green soon.
Leave from the field and change values of another textinput(this is just a textinput, this is a form there are some more form elemets), then come back to value exceeded textfield by SHIFT+TABS and remove the additional entered numbers, when you come to green soon your value is accepted.
Now again enter more values and now you are in the warn zone, then leave from the field and do the few changes in other form elements.
Then come back to the value exceeded text filed by MOUSE CLICK, and start delete from DEL, even though you removed additional values, still fields shows that you are in warn zone.
Actual Results:
Even when remove additional numbers,still field is Red
Expected Results:
if remove additional numbers, field should come its normal status.
Picture of this issue can be viewed at View Screen Shot