Can someone show me how should I correctly implement mathematical calculations like (+,-,/,*) using text inputs in 2 cases:
1 - more states
2 - input in a view an the result in other
Here is a part of my code:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="init()" currentState="State1" overlayControls="false" title="Calculator">
<s:states>
<s:State name="State1"/>
<s:State name="RezultatCalculator"/>
</s:states>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import spark.events.DropDownEvent;
protected function init():void
{
addEventListener(TransformGestureEvent.GESTURE_SWIPE, swipeHandler);
}
protected function swipeHandler(event:TransformGestureEvent):void
{
if (event.offsetX == 1)
{
navigator.pushView(CalculatorView);
}
}
protected function primulcalcul_openHandler(event:DropDownEvent):void
{
// TODO Auto-generated method stub
}
]]>
</fx:Script>
<s:Scroller includeIn="State1" left="3" right="3" top="0" height="547">
<s:VGroup width="100%" height="100%" gap="24" horizontalAlign="justify" paddingTop="8"
verticalAlign="top">
<s:Label id="actot" width="237" height="60" text="Active Totale" textAlign="center"
verticalAlign="middle"/>
<s:TextInput id="actot_val" width="183" height="60" fontFamily="_sans" fontSize="28"
textAlign="center" softKeyboardType="number" />
<s:Label id="disp" width="159" height="60" text="Disponibilitati" textAlign="center"
verticalAlign="middle"/>
<s:TextInput id="disp_val" width="164" height="60" fontFamily="_sans" fontSize="28"
textAlign="center" softKeyboardType="number"/>
<s:Label id="datot" width="159" height="60" text="Datorii Totale" textAlign="center"
verticalAlign="middle"/>
<s:TextInput id="datot_val" width="164" height="60" fontFamily="_sans"
fontSize="28" textAlign="center" softKeyboardType="number"/>
<s:Label id="caprop" width="159" height="60" fontSize="24" text="Capitaluri Proprii"
textAlign="center" verticalAlign="middle"/>
<s:TextInput id="caprop_val" width="164" height="60" fontFamily="_sans" fontSize="28"
textAlign="center" softKeyboardType="number"/>
<s:Button id="butstart0" width="401" height="70" label="START"
click="currentState='RezultatCalculator'" enabled="true"/>
</s:VGroup>
</s:Scroller>
<s:CalloutButton id="primulcalcul" includeIn="RezultatCalculator" x="22" y="28" width="145"
height="63" label="primulcalcul" enabled="true"
open="primulcalcul_openHandler(event)"/>
<s:TextArea id="Primul_val" includeIn="RezultatCalculator" x="203" y="27" width="267"
editable="false" prompt="result"/>
<fx:Script>
<![CDATA[
import flash.globalization.NumberFormatter;
import flashx.textLayout.formats.Float;
import flashx.textLayout.formats.Float;
import learnmath.mathml.components.MathMLFormula;
import learnmath.mathml.formula.layout.MathBox;
public function MathMLFormula():void
{
var Primul_val:Number=new Number
var datot:Number=new Number
var disp:Number=new Number
Primul_val=0
NumberFormatter(TextArea(Primul_val))==NumberFormatter(TextInput(datot))+NumberFormatter(TextInput(disp)); /* this is one of the examples, i tied some different values like valueOf */
}
]]>
</fx:Script>
</s:View>
I have a few suggestions, but I'm not sure exactly what your problem is.
First, use the restrict attribute on your TextArea. The restrict attribute will prevent people from entering non-numeric keys. Sort of like this:
<s:TextInput id="datot_val" width="164" height="60" fontFamily="_sans"
fontSize="28" textAlign="center" softKeyboardType="number" restrict="0-9"/>
It's entirely possible that the use of the softKeyboardType makes this a non-issue if you're using a mobile application on a device that supports it.
The line of code you mentioned in the comments looks to be error prone:
NumberFormatter(TextArea(Primul_val))==NumberFormatter(TextInput(datot))+NumberFormatter(TextInput(disp));
First, datot and disp are Labels; not TextInputs. They have hard coded non-numeric values. I think you want to use datot_val and disp_val. which are TextInputs. Since they are already inputs you do not need to cast them as such.
Second you do not need to cast the TextInput as a NumberFormatter. You would not usually use a NumberFormatter as a static class, but rather create an instance of it. More info on NumberFormatter here.
So, I believe your line would be rewritten like this:
Primul_val.text== String(
int(datot.text) + int(disp.text)
);
I added some extra lines so the parenthesis wouldn't get confused.
I take the input of datot (AKA datot.text) and cast it as an int. I take the input of disp (disp.text) and cast that as an int. I add the two together and convert them both to a String. The string is stored in the text value of Primul_val.
Does that help clear anything up?
Related
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
I have this 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"
autoDrawBackground="false">
<s:HGroup verticalAlign="middle">
<s:Button label="{data.Nome} ({data.Rating})" width="150" height="35"/>
<s:Button label="{data.Estado}" width="150" height="30"/>
</s:HGroup>
</s:ItemRenderer>
I'd like to see the properties of data object when typing . since its a custom object. How can I see them?
data is suppose to be a User class object.
Try this
<fx:Script>
<![CDATA[
import yourPackage.User;
[Bindable]
private var user:User;
override public function set data(value:Object):void{
super.data = value;
user = data as User;
}
]]>
</fx:Script>
<s:HGroup verticalAlign="middle">
<s:Button label="{user.Nome} ({user.Rating})" width="150" height="35"/>
<s:Button label="{user.Estado}" width="150" height="30"/>
</s:HGroup>
Either as Юрий Борыс said or you could also cast data as User:
<s:Button label="{User(data).Nome} ({User(data).Rating})" width="150" height="35"/>
HIH
In my code, I have a list made up of items from a dataprovider. The itemRenderer for the list consists of a BorderContainer with text in it. I'm mimicking a row of buttons on a scrolling list. I'd like the cursor to change to the hand cursor as it passes over the "button", but the pointer only changes in the part of the BorderContainer that isn't covered by the text.
I've set the buttonMode to true for the list, the BorderContainer, and the text, so why isn't the cursor changing when passing over the text?
This is the list code
<s:List id="listProject" width="100%" height="100%" horizontalScrollPolicy="off" allowMultipleSelection="false"
click="listProject_clickHandler(event)" itemRenderer="ProjectRenderer"
dataProvider="{listProjects}" creationComplete="listProject_creationCompleteHandler(event)" buttonMode="true">
And this is the renderer
<?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"
autoDrawBackground="true">
<!--<s:Label text="{data.header}"/>-->
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
<s:State name="selected"/>
</s:states>
<!--<s:Image source.normal="{data.image1}" source.hovered="{data.image2}"/>-->
<s:BorderContainer width="200" height="50" backgroundColor="{data.color}"
borderColor.selected="#FFFFFF" borderVisible.normal="false"
borderVisible.selected="true" borderWeight.selected="4" borderStyle.selected="inset" buttonMode="true">
<s:layout>
<s:HorizontalLayout verticalAlign="middle" horizontalAlign="center"/>
</s:layout>
<mx:Text width="200" text="{data.header}" selectable="false"
color="#FFFFFF" fontSize="15" fontWeight="bold" leading="0" textAlign="center" buttonMode="true" useHandCursor="true"/>
</s:BorderContainer>
</s:ItemRenderer>
Just use a Spark Label instead of mx:Text and you'll be fine.
Also, there's some redundancy in your code. I took the liberty of trimming it down a little:
<s:BorderContainer width="200" height="50" backgroundColor="{data.color}"
borderColor.selected="#FFFFFF" borderVisible.normal="false"
borderVisible.selected="true" borderWeight.selected="4"
borderStyle.selected="inset" buttonMode="true">
<s:Label text="{data.label}" color="#FFFFFF" fontSize="15" fontWeight="bold"
horizontalCenter="0" verticalCenter="0"/>
</s:BorderContainer>
This will also fix that nasty jumpiness of the text when hovered or selected.
As soon as you do not need interaction with mx:Text, you can set mouseChildren property of its parent to false. It will fix the problem. Here is a short example:
<s:ItemRenderer>
<s:BorderContainer width="200" buttonMode="true" useHandCursor="true" mouseChildren="false">
<mx:Text text="No many text" selectable="false" />
</s:BorderContainer>
</s:ItemRenderer>
Is there any way to create a parent view with sub view system in flex? For example I need to create an application that computes insurance rates for different products. All products need to have the same inputs for gender, age, and nicotine usage. What I'd like to do is have a 'parent view' (which wouldn't actually be displayed) that has all these basic fields layed out, then create sub views that automatically displays the components and layout of the parent view, which would cut back on duplicating code. the sub views would have additional components unique to the product (some would also need to take in number of children, etc.) and compute the rates in different ways.
Edit: let's say I have 2 different products. ProdA and ProdB
This is the view for ProdA
<?xml version="1.0" encoding="utf-8"?>
<components:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:components="spark.components.*" title="ProdA"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import ASClasses.LL;
public function makeLL(age:String, gen:String, nic:String):void{
var intAge:int=int(age);
var newLL:LL=new LL(intAge, gen, nic);
dest.text=String(newLL.computeRate());
}
]]>
</fx:Script>
<s:VGroup width="100%" height="100%" verticalAlign="middle" horizontalAlign="center">
<s:Label text="Age:"/>
<s:TextInput id="age" restrict="0-9" maxChars="2"/>
<s:ComboBox id="GenderBox" width="140" prompt="Gender" >
<s:dataProvider>
<mx:ArrayList>
<fx:String>Male</fx:String>
<fx:String>Female</fx:String>
</mx:ArrayList>
</s:dataProvider>
</s:ComboBox>
<s:Label text="The selected gender is: {GenderBox.selectedItem}"/>
<s:ComboBox id="NicotineBox" width="140" prompt="Nicotine Usage">
<s:dataProvider>
<mx:ArrayList>
<fx:String>Smoker</fx:String>
<fx:String>Non-Smoker</fx:String>
</mx:ArrayList>
</s:dataProvider>
</s:ComboBox>
<s:Label text="The selected Nicotine is: {NicotineBox.selectedItem}"/>
<s:Button label="Get Rate" click="makeLL(age.text, GenderBox.selectedItem, NicotineBox.selectedItem)" />
<s:TextInput id="dest" />
<s:Button label="Back" click="navigator.popView()" styleName="back" />
</s:VGroup>
This is the view for ProdB
<?xml version="1.0" encoding="utf-8"?>
<components:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:components="spark.components.*" title="ProdB"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import ASClasses.OP;
public function makePerson(age:String, gen:String, nic:String):void{
var intAge:int=int(age);
var newOP:OP=new OP(intAge, gen, nic);
dest.text=String(newOP.computeRate());
}
]]>
</fx:Script>
<s:VGroup width="100%" height="100%" verticalAlign="middle" horizontalAlign="center" >
<s:Label text="Age:"/>
<s:TextInput id="age" restrict="0-9" maxChars="2"/>
<s:ComboBox id="GenderBox" width="140" prompt="Gender">
<s:dataProvider>
<mx:ArrayList>
<fx:String>Male</fx:String>
<fx:String>Female</fx:String>
</mx:ArrayList>
</s:dataProvider>
</s:ComboBox>
<s:Label text="The selected gender is: {GenderBox.selectedItem}"/>
<s:ComboBox id="NicotineBox" width="140" prompt="Nicotine Usage">
<s:dataProvider>
<mx:ArrayList>
<fx:String>Smoker</fx:String>
<fx:String>Non-Smoker</fx:String>
</mx:ArrayList>
</s:dataProvider>
</s:ComboBox>
<s:Label text="The selected Nicotine is: {NicotineBox.selectedItem}"/>
<s:Button label="Get Rate" click="makePerson(age.text, GenderBox.selectedItem, NicotineBox.selectedItem)" />
<s:TextInput id="dest" />
<s:Button label="Back" click="navigator.popView()" styleName="back" />
</s:VGroup>
Almost all the code is the same except for a few differences. I'd like to have one view (Product) that contains all the duplicated code, then have ProdA and ProdB extend this product. So that everything in the Product view shows up in both ProdA and ProdB
Use dependency injection (expose public properties that you can then bind to within the View), which frees you from having to define the whole thing inline as shown above. it would look something like this
[Bindable]
public var dataProvider:ArrayList
//..other public vars
<s:ComboBox id="combo" width="140" prompt="{promptPublicVar}" >
<s:dataProvider>{dataProviderPublicVar}</s:dataProvider>
<s:change>publicVarContainingSelection=combo.selectedItem</s:change>
</s:ComboBox>
<s:Label text="{label}: {publicVarContainingSelection}"/>
And you'd use it something like
<myNS:MyView>
<myNS:prompt>Gender</myNS:prompt>
<myNS:dataProvider><mx:ArrayList>...</mx:ArrayList></myNS:dataProvider>
<myNS:label>The selected Gender is: </myNS:label>
</myNS:MyView>
===========not going to write any more code to try to guess what you want, so============
here are some patterns you might find useful:
Presentation Model
Abstract Classes
Template Components
Note that the third link also mentions Code behind, which can be used as a type of abstract class.
Also, you might want to consider composition over inheritance. For example, your view shouldn't know or care how to calculate rate information, but could have a rate calculator data component passed to it. Which it most emphatically should not be creating for itself--this is one of the reasons you're having such a hard time arriving at a reusable design.
I am trying to implement some MVC-style UI components in Flex 4. I want to further separate the visual setup (and later runtime modification) of each element. Primarily, I want to keep the overall layout of the data like such in the MXML file that will USE the skin:
<s:Group id="container">
<s:VGroup>
<s:HGroup id="titleGroup">
<s:Label id="titleText" />
<s:Button id="closeButton" />
</s:HGroup>
<s:HGroup id="contentGroup">
<s:VGroup id="interactionGroup">
<s:VGroup id="messageGroup" />
<s:HGroup id="actionGroup" />
</s:VGroup>
</s:HGroup>
</s:VGroup>
</s:Group>
And in the Skin file, I want to be able to refer to the ids and set properties on them (such as width and height on the "container" group) AND be able to include graphical elements within them (such as a filled rect inside the "container" group). I want to do this declaratively, NOT programmatically, else why use MXML in the first place? This is the way that HTML/CSS is divided up: HTML contains what the data IS relative to other data, and the CSS contains all the properties and visual styles.
As it is now, my skin looks like this:
<s:Group id="container" verticalCenter="0" horizontalCenter="0">
<s:Rect id="background" width="100%" height="100%" radiusX="10" radiusY="10">
<s:filters>
<s:DropShadowFilter blurX="20" blurY="20" alpha="0.32" distance="5" angle="90" />
</s:filters>
<s:fill>
<s:SolidColor color="#ffffff" />
</s:fill>
</s:Rect>
<s:VGroup width="100%" height="100%" gap="3" paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
<s:HGroup id="titleGroup" width="100%" verticalAlign="middle">
<s:Label id="titleText" width="100%" />
<s:Button id="closeButton" />
</s:HGroup>
<s:HGroup id="contentGroup" width="100%">
<s:VGroup id="interactionGroup" width="100%">
<s:VGroup id="messageGroup" width="100%" />
<s:HGroup id="actionGroup" width="100%" />
</s:VGroup>
</s:HGroup>
</s:VGroup>
</s:Group>
And the actual component that uses this skin is nothing more than SkinPart declarations:
<fx:Script>
<![CDATA[
import spark.components.Label;
import spark.components.Button;
import spark.components.Group;
[SkinPart(required="true")]
public var titleText:Label;
[SkinPart(required="true")]
public var closeButton:Button
[SkinPart(required="true")]
public var messageGroup:Group;
[SkinPart(required="true")]
public var actionGroup:Group;
]]>
</fx:Script>
As you can see, the Skin contains everything about the component, violating my sense of separating style and content. The using element has nothing in it except for interfaces to the Skin for programmatic changes. My current solution has no advantage over not using skins at all, except for the slightly easier process of switching out skins.
Is there a way to do what I have proposed in Flex 4?
The answer is that Flex does not work this way. Layout and visual style appear to be inseparably linked. Closing out this question.