(First off, I have already posted this on the Telerik forums (link), but this site gets more traffic, so I'm hoping to get some help sooner.)
I am trying to achieve some custom value formatting with the CurrencyTextBox, but the way that the control handles values is making things decidedly hard.
What I want to do is this: if the user enters a value that does not contain a "." character, it will format that value as cents instead of dollars. So if a user enters "16", I want the control to display (and contain a value of) $0.16. If the user enters a value with a ".", I would like the control to function as normal. If the user enters "16.", "16.0" or "16.00", I want the control to display (and contain a value of) "$16.00". This application will be used by people in the retail business and this is how they expect inputs for price values to function.
However, whether I subscribe to the OnChange event or even the "blur" event on the textbox itself, it is stripping the "." character if there is either nothing after it or only 0's after it. Example: If I enter in a value of "16.", "16.0" or "16.00", the value pulled from the textbox in javascript will be "16". And since I have to check for the presence of the "." character, this breaks my logic to properly format the value.
So I'm looking for some help or suggestions. Here is the javascript that I have right now to properly format the value as required. As you can see, if the value does not contain a "." character, the value is divided by 100, which is exactly what I want. Stripping this character is killing my logic. :)
$('custom-price').find('input').live('blur', function (e) {
var sender = $(this).data('tTextBox');
var priceVal = $(this).val(); // $(this).attr('value') also returns the value with the character stripped, FYI
if (priceVal.indexOf(".") == -1) {
priceVal = priceVal / 100;
}
sender.value(priceVal);
});
Try the same using ascii code for "." operator (46). OnKeyPress if you find ascii code 46 change the format for control..
Regards,
Dhaval Shukla
Related
I have a listbox with 2 columns (say "from time" and "to time"). I want to filter user input by 24 hour format only i.e. no other key should be allowed to press except 24 hour time format (i.e 00:00 to 24:00) in the cell. I tried with this: &"0-2"#&"0-3"#:& "0-5"#&"0-9"# it works well but it didn't allow to put something 19:22 or the value after 13:59 in the cell value as I haven't passed other optional value for that 24 hour time format. In regex, it's a bit easy to achieve this ('/^([01][0-9]|2[0-3]):([0-5][0-9])$/') but not sure how this can be done in the 4d database listbox cell field.
Any help would be appreciated. Thanks.
I suggest you make the list box columns text and manage the display and UI yourself if you require fine control over the input values.
The Time string method will convert a time value for you:
$timeStr:=Time string(Current time) // $timeStr = "07:23:45"
The input filters are not RegEx and will not give you the kind of fine control you need. They will let you filter unwanted characters (anything besides numbers for instance). Try this for the Entry Filter on the column
!0&9##:##:##
The result will be a text string of the numbers entered. Write a method to take the input string, parse the elements, validate them, update the data source and then return a properly formatted string for display. I would use the On data change form event as the trigger for running the method.
$h:=Num(Substring($inputStr;1;2))
$m:=Num(Substring($inputStr;3;2))
$s:=Num(Substring($inputStr;5;2))
Recent versions of 4D manage time values as seconds since midnight which is why you may get a longint value instead of a 'time' value sometimes. And depending on which version you are using and the type of listbox (collection, entity selection, array, etc.) you may not even have a 'time' type option for the list box column which can be confusing. Given all that it's just easier to stringify the value and work with that.
For example, what do you want to do if a user enters "33:45:00"? If you want to reject the "33" at the outset you can do this by evaluating each character as it is typed. The On After Keystroke form event lets you run your evaluation method after each change in the field and the Get edited text command allows you to see what the user is entering. https://doc.4d.com/4Dv18R3/4D/18-R3/Get-edited-text.301-4901376.en.html
To convert a string (or longint) into a time value use the Time method:
$timeVar:=Time($timeStr)
4D is a typed language and has had a time type since the beginning. However with the addition of ORDA some UI objects no longer support the time type (collection and entity selection list boxes, for example) and use a longint type instead. This can be confusing if you are working with an existing app or older code but attempting to use the newer tools. Be sure to look over
https://developer.4d.com/docs/en/Concepts/time.html
and
https://doc.4d.com/4Dv18/4D/18/Date-and-Time.201-4504355.en.html
You may not need to get so involved in the input. It depends on the nature of the UI and the data. Time and date is tricky in just about every platform.
I have like a POS application where I work, and I added new code to read barcodes in a datawindow, but been having some problems to use it correctly. The process needs to read the barcode and automatically search for the product, and insert it in another datawindow with the info regarding the product.
The problem is that I have the code in the editchanged event, and that the barcodes have different lenght; so, every time a number of the barcode is read, the search function is called, here is the code for that function:
ll_rtn = dw_search.Retrieve()
If ll_rtn = 1 Then
is_code = dw_search.GetItemString(1,'barcode')
wf_insert(False)
End If
If for example, a product of 10 digits is read and at length 5 the product is found, it's inserted but the editchanged is still running because the barcode is length 10, and depends of the search, might find it again with the last digits and insert it again.
I don't know how to stop reading after I find the product. Hope I explain it right.
Can you check if the barcode scanner can be configured to pass carriage return / Enter, upon scanning the barcode and this way you can move your code to itemchanged event
Bar Code Config
An editchanged event is fired for each keystroke in the control. You probably want to either move the code to the itemchanged event or to a totally separate event which is posted from the itemchanged event.
If you absolutely have to have the code in the editchanged event you need to set a boolean instance variable on the window which is set TRUE once the product is found. If it's true then don't search. Remember to reset the variable to FALSE prior to any new search.
I have time for example I have in records time written in this way: 00:02:24 or 15:22:45, and now I want to make another column (hours), where can be values for example for time 02:43:22 is value 2, or for time 23:22:14, is value 23 and so on. But I don't know how can I do that, I tried number range, but unsuccessfully.
Here is a picture, how i want to be:
Thanks.
You can use the Modified JavaScript Value step.
I do not know which type is your Time.
If it is a String, a var Hour = Time.substr(0,2); will do.
If it is a Date, use var Hour = Time.getHour();.
If the type is something else, then convert in a String first.
To do this:
drag-and.drop the step Modified JavaScript Valueand link it to the data flow provider (in the example a Data grid).
edit this step and add your script. (Note that you can quickly add the input variable with a double click. Note also that clicking on the Transformation Function in the left menu gives you the list of available function additional to the Javascript built-in collection).
Click on the Get variable button, keep the variable you need (here Hour), and define/redefine its type (here String).
That's done: OK and preview.
If needed, adapt to the type of your input flow. For example Hour = Hour+'' to force a type conversion into a String.
I have a very standard binding set up in android on a UITextView
local:MvxBind="Text Quantity"
Where Quantity is an int property.
If I enter 123 say, that gets assigned and the setter is called. As I delete that text, 123 -> 12 -> 1 -> empty string, the setter is called for each number but not for the empty string infact the following exception occurs:
MvxBind:Error: 48.84 SetValue failed with exception - FormatException: Input string was not in the correct format
Is there a way of automatically converting the empty string value to 0 in the binding? Will I need a value converter for this? Is this in fact a bug?
Thanks in advance.
This area has been discussed recently in https://github.com/slodge/MvvmCross/issues/350 with some nullable additions in https://github.com/slodge/MvvmCross/issues/373 - people are welcome to contribute their opinions (and/or code) there.
The current 'status quo' is that MvvmCross will parse and represent valid decimal numbers. However, if the number isn't valid - eg if it's string.Empty or a set of non-numeric characters - then MvvmCross won't interpret these as zero (should "" be zero? should "asdf" be zero? should "123.456.7" be zero? should "1234asd" be zero? perhaps all of these should actually be NaN?).
If people need specific behaviour then it's easy for them to implement this behaviour - e.g. using a custom control (subclassed UITextField), using a value converter, using a custom binding (or overriding the default binding), using a string property on the viewModel, etc.
My personal opinion is that this topic really comes under the Validation heading. In general, MvvmCross doesn't provide many hooks for Validation at present. It's been proposed for a long time - https://github.com/slodge/MvvmCross/issues/133 - but no-one has shown much interest. There are some simple validation samples in the WithErrors demo within https://github.com/slodge/MvvmCross-Tutorials/tree/master/ApiExamples. Within the apps I've written we've generally written and sub-classed UI controls to help reduce the need for validation - and in general we've tried to avoid the need for as much text input as we can (users don't like seem to like using keypads on phones)
I am writing a button calculator. I have the code split into model, view and a controller. The model knows nothing about formatting, it is only concerned with numbers. All formatting is done in the view. The model gets its input as keypresses, each keypress is a part of an enum:
typedef enum {
kButtonUnknown = 0,
kButtonMemoryClear = 100,
kButtonMemoryPlus = 112,
kButtonMemoryMinus = 109,
kButtonMemoryRecall = 114,
kButtonClear = 99,
…
};
When the user presses a button (say 1), the model receives a button code (kButtonNum1), adds the corresponding number to a string input buffer ("1") and updates the numeric output value (1.0). The controller then passes the numeric output value to the view that formats it (1).
This is all plain, simple and clean, but does not really work. The problem is that when user enters a part of a number (say 0.00, going to enter 0.001), the input does not survive the way through model to view and the display says 0 instead of 0.00. I know why this happens ("0.00"::string parses to 0::double and that gets formatted as 0). What I don’t know is how to design the calculator so that the code stays clean and simple and the numbers will show up on screen exactly as the user types them.
I’ve already come with some kind of solution, but that’s essentially a hack and breaks the beautiful and simple flow from the calculator model to the display.
Ideas?
Current solution keeps track of the calculator state. If the calculator is building a number, I take the calculator input buffer (a string) and directly set the display contents (also a string). Otherwise I take the proper path, ie. take the numeric calculator output, pass it to the view as a double and the view uses its internal formatter to create a string for the display. Example input:
input | display | mode
------+---------+------------
0 | 0 | from string
0. | 0. | from string
0.0 | 0.0 | from string
0.0+ | 0 | from number
This is ugly. (1) The calculator has to expose its input buffer and state. (2) The view has to expose its display and allow setting its contents directly using a string. (3) I have to duplicate some of the formatting code to format the string I got from the calculator input buffer. If user enters 12345.000, I have to display 12,345.000 and therefore I’ve got to have a commification code for strings. Yuck.
On my calculator (HP48SX) the numbers in the display are formatted according to the settings for displaying numbers. Right now, if I enter 0.00 (or any variant thereof) it is displayed as 0.0000. Perhaps you could separate display (ie formatting) from internal number representation ? In terms of MVC I guess that this would be implemented as state in the C.
EDIT in response to OP's comment. I don't fully understand the limitations of what you call a button calculator so you're on your own there. As for separation, I would design the calculator such that:
Model is always working with whatever you use for representing numbers: floats, doubles, decimals, what-have-you.
View is always working with strings which present numbers nicely and allow users to enter as they wish.
Controller translates from string to number, from number to string. In my original suggestion I envisaged that Controller itself would be stateful (storing current-numeric-format for example) and be addressable from the buttons. But you seem to have ruled that out.
Your problem, as I see it, is that if you don't store this state somewhere then you have no way of telling the calculator to use anything other than a fixed* format for displaying any number entered. By fixed* I mean a very limited form of flexibility, such as always displaying the number of decimal digits that were in the most recently entered number, rather than absolutely fixed such as 12 digits, no more and no less.
At last I’ve found a nicer solution. I have added an inputHint property to the formatter object that takes care of the output formatting in the view. This input hint receives the value of the calculator input buffer and affects the formatting. If there is a decimal dot in the input hint, the formatter is forced to always keep the decimal dot in output, therefore solving the case of "0." being formatted as "0". And if the input contains some fraction digits, the formatter is forced to keep the same number of fraction digits in output (solves the case of "0.00" being formatted as "0").
I still have to expose the calculator input buffer and state, but I don’t have to expose the view’s display as string and don’t have to maintain the duplicate formatting code path for strings.