AlphaGit / ng-pattern-restrict

Allowing only certain inputs based on a regex pattern, for AngularJS
http://alphagit.github.io/ng-pattern-restrict/
MIT License
47 stars 32 forks source link

Input type=number on Chrome will clear field if "restricted" text is typed while having text highlighted #52

Closed aplocher closed 6 years ago

aplocher commented 7 years ago

When you hit the TAB key to tab between fields, it generally will highlight the text in that field. In the case of input type=number on Chrome, if you type in a character that is not supported, it will reject the input, but it also clears the currently selected value.

In Chrome with input type=text, it properly prevents the input and does NOT clear the textbox

It also works properly with FireFox with input type=text and type=number (does not allow input, does not clear textbox).

d

AlphaGit commented 7 years ago

Hi @aplocher! Thank you for your report.

Here's an explanation of what is going on: when you setup a value or enter a valid value, ng-pattern-restrict will detect that it's valid and save it, so whenever you enter a key that makes the value invalid, it can restore the text to the previous value and it can also set the caret in the old position, giving the user the impression that "nothing happened".

Input type=number are trickier, because they will NOT provide the value of the textbox when the value is not numeric. This means that ng-pattern-restrict can only rely on the browser's validity state for the input. If the browser says it's invalid, well, it's invalid (even if it matched the regex). If the browser says it's valid, then we get the value and we can really test.

This will explain why your reported issue can only be reproduced if you enter a non-numeric value. For example, with regex ^[123]*$ in a numeric input, you can type "6" and the previous value will remain. I tested it out with this setup:

<input type="number" ng-pattern-restrict="^[123]*$" value="1" />

However, the fact that the value is cleared when you enter a non-numeric value is something that Chrome performs and not ng-pattern-restrict.

Add a numeric textbox to any page, tab into it, enter "a" and see that Chrome and Firefox will display the exact same behavior that you're describing.

Unless there's anything else that we need to do, I'm tempted to say this is a browser behavior and nothing that the library is doing.

Let me know if my assessment is correct.

Thanks!

aplocher commented 7 years ago

Hi @AlphaGit thanks for your response.

I should have mentioned in my original post... yes I absolutely think it's a behavior of Chrome. I guess it depends on how much browser-specific code you're willing to have muddy up your library (which, as a developer, I feel your pain there).

I actually stumbled across this library while trying to implement my own number-only textbox directive. Initially I had it setup to use input type=number and TRUST ME, I never expected to spend SO many hours trying to do something SO simple. I finally stumbled across this and implemented it (I love it, btw), and I just ended up going back to use INPUT TYPE=TEXT.

When I was messing with it, I did have limited luck with this I believe:

element.bind('keydown keypress keyup', function(event) {
    console.log(event);
    if (/[^0-9]/.test(event.key)) {
            event.preventDefault();
    }
});

Although, now that I'm looking at it, I believe that's using JQuery. It was a late night and I was in desperate need of caffeine or sleep. I think it can be done, at least on a key-by-key basis which would be very difficult (maybe impossible?) to hook up with a full regex match that looks at more than just a single character at a time.

I think I could have made it work for my purpose (just a plain number matcher), but I stumbled on your lib on a SO post, checked it out, and didn't touch that "keypress" code again.

So I guess it's just good to bring this to your attention, but this can probably be closed unless it's something you wish to explore further.

Thanks!

AlphaGit commented 7 years ago

@aplocher Thank for the quick and understanding response!

Yes, I would personally try not to play a lot with trying to level up browser behaviors. First, it's an area of very limited mobility (it's very likely we won't be able to address all of our needs), and second, the new types of inputs introduced by HTML5 are really a problem when it comes to cross-browser experience. Half of the internet is still complaining about the lack of styling, the lack of user experience consistency, and let's not even introduce mobile browsers into the mix.

This is a subject that could be useful to address if consistency was a major goal, but there's a huge amount of effort in development and maintenance. I don't think that's the behavior we'd like for this library, which is mostly an "add-on" to inputs.

I actually stumbled across this library while trying to implement my own number-only textbox directive. Initially I had it setup to use input type=number and TRUST ME, I never expected to spend SO many hours trying to do something SO simple

If it makes you feel better, it sounds simple but there are way too many gotchas around this. Some of those are unavoidable. For example, if you allow for user pasting input, which is differently based on the browser and browser version. It is also different if the user does a right-click paste or keyboard paste, regarding the events that you can catch.


Your approach looks good (it doesn't seem to be using jQuery, which is better if you try to keep your dependencies to a minimum). However, as I mentioned, it will not be a catch-all, but will prevent a good majority of cases.

Depending on your particular requirements, I think the best bet you can have is react on the blur event and validate the final string, telling the user something is wrong and they need to correct. If your quantity was indeed a quantitative value, then an input type=number was a good start, but also remember you won't have much control on the steps taken.

And, of course, if this data gets sent to the server you need to validate it there too anyway, so it all depends on what experience you want to give to a user. Using this library (because of its approach) is actually not the recommended approach. Imagine your users suddenly becoming confused because they typed a key and it does not work. It all depends on your users and your requirements, really.


If you don't mind, I'll proceed to close this ticket, as we won't be addressing the inconsistency between browsers.

Feel free to reach out to me if you wish to continue this conversation. :)