Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users to enter out-of-bound numbers, outside of the minimumValue and maximumValue range #543

Closed
AlexandreBonneau opened this issue Jan 12, 2018 · 24 comments

Comments

@AlexandreBonneau
Copy link
Member

Currently, if a user sets the minimumValue option to a value superior to zero, it effectively prevent him to delete the input value, since it would mean the rawValue would be equal to 0.

While this is exactly what the minimumValue option is for, I see a use case where users would want to be able to temporarily clear the element, in order to type their valid values.

Allowing this will bring some side effects:

  • First, the rawValue will be updated with a potential incorrect out of range value while the user is typing it (the user would then need to manage those error cases),
  • Second, we would need to allow not only the value 0, but any values between 0 and the minimumValue
    • For instance this means that if we have a minimumValue set to 1234, then we would need to allow the user to type 1, 12 and 123 before finally accepting the correct value 1234.

To that end, we would need to create a new option overrideMinimumValueLimitation (or something equivalent) set to false by default, that would allow a user to input values between 0 and minimumValue in the element, and would then revert to the last good known value on blur if it's still equal out of range.

This seems not trivial.

@alexmojaki
Copy link

I would suggest a different API. Leave the behaviour of minimumValue as is, and add another option softMinimumValue. This would behave similar to the min attribute of a normal HTML <input type="number"> by setting some sort of state on the control (perhaps a class to allow styling). minimumValue and softMinimumValue would be independent and each can be set on their own, or they can be set together as long as the soft value is lower (otherwise it would be useless).

The main advantage of this API is that someone migrating their interface from traditional number inputs to autonumeric can easily preserve the original behaviour. More generally, autonumeric will more closely resemble the widely used standard that everyone expects. People are familiar with controls that let you type in an invalid value but notify you of the problem.

On the other hand, a control that suddenly reverts its value would be astonishing, confusing, and possibly lead to errors. Suppose a field contains a valid value but the user decides to change it to an invalid value, and while the field is still focused and containing this invalid value, they click submit. The field would blur before the submit and the user could unknowingly submit a value they explicitly didn't want.

@AlexandreBonneau
Copy link
Member Author

AlexandreBonneau commented Jan 16, 2018

You're right, changing the invalid value back after the user modified it is bad UX.

Having a specific softMinimumValue option could be more simple to implement (I'm not sure about the name yet).

However there are still many use cases to analyze since until now, AutoNumeric always assumed that the values stored in its element and internally were valid.

We'd have to change all the event handlers (mouseover, mouseout, focus, blur, keydown, keyup, etc.) to accept an invalid value, for the formatted and rawValue.

If we go down this road, we could also modify the form*() functions to only submit if all the AutoNumeric elements contains valid values.

@marco2250
Copy link

I don't think a new option is necessary.

What I think that would be pretty reasonable, is to do kind of a 2 step validation:

  1. While typing. Lets allow the user to input till I can guarantee the number is valid. So, if minimum value is 120000 and I try to start typing with a '0', do not let it to type it! Then, if I type '1', allow it. After '1', type '0', do not allow it, an so on.

  2. On the 'change' event. In this case, if an invalid vale occurs, you just 'clear' the field value. In this case, one could use a library, like popover, to tell the user he or she entered an invalid value, setting the focus into it. BTW, I agree with POLA. But... Let's think... What if, in my car, I forgot to 'deactivate' the hand brake, and press the accelerator. Is it supposed that my car start moving? Of course not... I think the same concept applies to this step 2.

Finally, do you think, from the end-user point of view, that would be "natural" to be allowed only to paste the value? In fact, that situation is the one which breaks the POLA.

Got the point?

Thank you.

@AlexandreBonneau
Copy link
Member Author

AlexandreBonneau commented Aug 24, 2018

On the 'change' event. In this case, if an invalid vale occurs, you just 'clear' the field value.

As stated in the previous comments, changing the value once the user blur it would be bad UX and would mostly confuse users.

While typing. Lets allow the user to input till I can guarantee the number is valid

What should happen if the user never enters a valid value?

@AlexandreBonneau
Copy link
Member Author

AlexandreBonneau commented Aug 24, 2018

One solution could be to modify the overrideMinMaxLimits option and add a 'temporary' choice to it, so it would ignore the minimumValue and maximumValue limits and allow the user to enter any numbers, but at the same time would set the invalid state to the input or DOM element if the value is out of bound.

Would that work for you guys?

EDIT: Or, do not even add any new choice to the option, and set the invalid state for all 'ceiling', 'floor' and 'ignore' if the value is out of bound?

@alexmojaki
Copy link

@marco2250 your first step doesn't really make sense. Any digit could be a step towards a valid value. Maybe the user is trying to type 555555 or 1000000. The only exception is a 0 while the field is still empty.

@marco2250
Copy link

With all due respect, for now, what I know is that the minimumValue and maximumValue are useless, as they do not address real world situations.

Anyway, again, congratulations for the component.

@MannikJ
Copy link

MannikJ commented Mar 23, 2019

Is there any progress on this?

I really like autonumeric for all it does, but as already said, the minimumValue feature ist just useless if it behaves like this.

Can someone suggest a good workaround to at least avoid submitting data via ajax that differs from the input the user sees? I use the the vue-autonumeric component.

@AlexandreBonneau
Copy link
Member Author

Can someone suggest a good workaround to at least avoid submitting data via ajax that differs from the input the user sees? I use the the vue-autonumeric component.

What do you mean by data [...] that differs from the input the user sees?
Right now AutoNumeric will only ever accept valid values according to the options you specified, hence the data you see should be coherent with the data you send with ajax.
Did we miss something?

@MannikJ
Copy link

MannikJ commented Mar 25, 2019

https://codepen.io/mannikj/pen/MxxoLx
What I mean is that is if you delete the content of the autonumeric field with the minimumValue applied so that the input value is smaller that the minimum, the input is in a state where the displayed input content differs from the value of the model. It is actually really a broken state, because you can't even type anymore until you cancel the editing which resets it to last valid value. You can only type if the typed value leads to an overall input value above the minimum.

Although you are right that it would be quite hard to really submit that wrong data unintentionally, because the next user action will just reset the input instead of submitting it right away

@AlexandreBonneau
Copy link
Member Author

Right now AutoNumeric will only ever accept valid values according to the options you specified, hence the data you see should be coherent with the data you send with ajax.
Did we miss something?

Turns out I'm a bit wrong here since we allow the user to delete the entire content of the field while the minimum value is higher than 0. Perhaps we should prevent that behavior.

@MannikJ
Copy link

MannikJ commented Apr 8, 2019

Did you look at the codepen?
I think deleting all input should be allowed no matter what the minimumValue is. You never know what the user wants to type in the end. I don't think preventing the user from deletion is very intuitive.
The cucial part is that with the current implementation the bound value does not reflect what you see. So you are not even able to validate that edge case on your own which would probably be the best anyway, All other options I can think of are quite opinionated and unflexible.

@AlexandreBonneau AlexandreBonneau pinned this issue Apr 15, 2019
@amjadkhan
Copy link

This is also tripping me up. I need a min value > 0. My allowed range is > 25 and <= 100. Why not check the value on blur because as other commenters have mentioned, you don't know the intention of the user - I want to enter 100 but 1 < 25 so I am not allowed to enter the first character.

@AlexandreBonneau
Copy link
Member Author

One solution could be to modify the overrideMinMaxLimits option and add a 'temporary' choice to it, so it would ignore the minimumValue and maximumValue limits and allow the user to enter any numbers, but at the same time would set the invalid state to the input or DOM element if the value is out of bound.

Would that work for you guys?

EDIT: Or, do not even add any new choice to the option, and set the invalid state for all 'ceiling', 'floor' and 'ignore' if the value is out of bound?

So, to sum up, to 'fix' the current behavior, we could:

  1. Allow the user to empty the field at all times, even if the minimumValue is higher than 0
  2. Allow the user to enter any number, even if that one is out of bounds
  3. While the rawValue entered is out of bounds, add the invalid state to the input
  4. Allow the user to blur the invalid field, without changing its value
  5. Entering a number within the limit boundaries would remove the invalid state
  6. This would be the default behavior

This means this would affect how the overrideMinMaxLimits option works.

  • doNotOverride, which is the default, would allow temporary out-of-bound values whilst setting the invalid state on the field
    • When the value is correctly within the limit boundaries, the invalid state is removed
  • ceiling would strictly adhere to maximumValue and ignore minimumValue
    • the user would be allowed to enter anything between -∞ and maximumValue.
    • If maximumValue is less than 0, then it would allow emptying the field and typing value comprised between maximumValue and 0 (and hence setting the invalid state)
  • floor would strictly adhere to minimumValue and ignore maximumValue
    • the user would be allowed to enter anything between minimumValue and +∞.
    • If minimumValue is higher than 0, then it would allow emptying the field and typing value comprised between 0 and minimumValue (and hence setting the invalid state)
  • ignore would ignore both minimumValue and maximumValue
    • as before, hence the field would always be valid
  • never would keep the current behavior that would prevent the input to ever have an invalid state
    • this would be a new option

Thoughts?

@vince83110
Copy link

Please review the documentation, for now it's :

The minimum value that can be entered (-10 trillions by default)

Which is clearly wrong. I agree, this option is useless and the documentation dangerous. You should remove this option, since you have already floatPos or intPos to define 0 as a minimum. Weird thing really.

@AlexandreBonneau
Copy link
Member Author

Please review the documentation, for now it's :

The minimum value that can be entered (-10 trillions by default)

Which is clearly wrong.

I'm not sure how you get to that conclusion, but the default minimum value really is -10 trillions.
You can check that on the default AutoNumeric element on http://autonumeric.org/.

See the screenshot.

@vince83110
Copy link

If I put 20, or any positive number, user can't enter anything. So yes it's wrong. Not about the default value, but the behavior of this option doesn't allow to enter anything.

@kaikun213
Copy link

@AlexandreBonneau I think that sounds reasonable.

Additionally I would add that in any case (even if overrideMinMaxLimits is set to never) the input field should have some small indication if an invalid number was tried. E.g. a red boundary which vanishes again after two seconds. As without any error indication it is very confusing for the user. This could also be a quick fix for the current version.

What do you think?

@AlexandreBonneau AlexandreBonneau changed the title Add an overrideMinimumValueLimitation option to allow temporarily entering values between 0 and minimumValue when the latter is superior to zero Allow users to enter out-of-bound numbers, outside of the minimumValue and maximumValue range Apr 9, 2020
@AlexandreBonneau
Copy link
Member Author

AlexandreBonneau commented Apr 9, 2020

So, considering having 0 out of the minimum/maximum range is pretty rare compared to the usual use cases, I will not change the default behavior ; by default, the overrideMinMaxLimits setting will still use the doNotOverride option.

However, I see the use case for being able to enter invalid numbers.
To allow that, I had two choices before me, either use those options :

- 'ceiling' strictly adheres to `maximumValue` and ignores the `minimumValue` settings
            It allows the user to enter anything between -∞ `and maximumValue`.
            If `maximumValue` is less than 0, then it will allow emptying the field and typing a value between `maximumValue` and 0 (and hence setting the invalid state)
- 'floor'   strictly adheres to `minimumValue` and ignores the `maximumValue` settings
            It allows the user to enter anything between `minimumValue` and +∞.
            If `minimumValue` is higher than 0, then it will allow emptying the field and typing a value between 0 and `minimumValue` (and hence setting the invalid state)
- 'ignore'  ignores both the `minimumValue` and `maximumValue` settings
            When using this option, the field will always be valid range-wise
- 'never'   strictly adheres to the `maximumValue` and `minimumValue` settings
            Use this if you want to _always_ have a valid input in the field (This is how AutoNumeric has always behaved before `4.6.0`).
            Note: If `0` is out of the min/max range, this will prevent the user clearing the input field.
- 'doNotOverride' This is the default behavior.
                  The user can temporarily type out-of-bound values. In doing so, the invalid state is set on the field.
                  When the value is correctly set within the limit boundaries, the invalid state is removed.

...or uses those:

- 'ceiling' Strictly adheres to `maximumValue` and ignores the `minimumValue` settings
            It allows the user to enter anything between -∞ `and maximumValue`
            If `maximumValue` is less than 0, then it will prevent the user emptying the field or typing value above `maximumValue`, making sure the value entered is always valid
- 'floor'   Strictly adheres to `minimumValue` and ignores the `maximumValue` settings
            It allows the user to enter anything between `minimumValue` and +∞
            If `minimumValue` is higher than 0, then it will prevent the user emptying the field or typing value below `minimumValue`, making sure the value entered is always valid
- 'ignore'  Ignores both the `minimumValue` and `maximumValue` settings
            When using this option, the field will always be valid range-wise
- 'doNotOverride' Strictly adheres to the `maximumValue` and `minimumValue` settings
                  This is the default behavior
                  If `0` is out of the min/max range, this will prevent the user clearing the input field, making sure the value entered is always valid
- 'invalid' The user can temporarily type out-of-bound values. In doing so, the invalid state is set on the field.
            When the value is correctly set within the limit boundaries, the invalid state is removed

I chose the latter, with the new invalid option for the overrideMinMaxLimits setting.

This will allow, I hope, minimal changes to the codebase keeping the code as simple as possible. This way, most current users will not have to update their settings since the default won't change. Users wanting to be able to enter invalid numbers will be able to.
This is a work-in-progress issue.

Edit: Do note that the invalid state cannot be set on a contenteditable-enabled element (see the tests).

@AlexandreBonneau
Copy link
Member Author

@kaikun213 I'm not keen adding timeouts to AutoNumeric elements.

You can already listen to the 'autoNumeric:minExceeded' and 'autoNumeric:maxExceeded' events that are sent when the range is crossed, and create your own visual feedback.

@AlexandreBonneau
Copy link
Member Author

It took 2 years, but it's finally here ;)

The latest AutoNumeric version 4.6.0 integrates the new 'invalid' option for the overrideMinMaxLimits setting.
Using that will allow you to solve your problem.

@kaikun213
Copy link

Great, I think the documentation is still missing the new option http://autonumeric.org/configurator @AlexandreBonneau

@PedroDuarte536
Copy link

Not sure if this is the proper place, but with the latest version (4.6) I've solved what I believe that was intended with the following code:

let resetVal = () => AutoNumeric.getAutoNumericElement(elem).set(min); elem.addEventListener('autoNumeric:minExceeded', () => elem.addEventListener('blur', resetVal, false)) elem.addEventListener('autoNumeric:correctedValue', () => elem.removeEventListener('blur', resetVal, false))

@djohle
Copy link

djohle commented Jan 11, 2023

It took 2 years, but it's finally here ;)

The latest AutoNumeric version 4.6.0 integrates the new 'invalid' option for the overrideMinMaxLimits setting. Using that will allow you to solve your problem.

While this setting can be helpful, such as being able to use CSS to highlight a bad value, that is still not really addressing the original problem. Or rather, it's just shifting the problem elsewhere.

Here is a test case that is similar to my situation, where I want to have optional fields in a form, but still limit the range of values a user can enter. As such, it is a strange UI to indicate a problem with a field that isn't even required.

Here is a test case I created that shows a lot of odd behaviors as a result of trying to use this new setting...
https://jsfiddle.net/rz7Lgfne/6

  1. Not entering anything anywhere, just hovering an input box it results in a invalid indicator
  2. Entering a value and then clearing it results in a invalid indicator
  3. You are able to enter values outside the range, completely defeating the purpose of defining a range

Really I just want to allow null/empty values in addition to the defined range (i.e. not treating empty as invalid).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants