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

Limit Input characters #3508

Closed
willmcgugan opened this issue Oct 11, 2023 · 6 comments · Fixed by #3657
Closed

Limit Input characters #3508

willmcgugan opened this issue Oct 11, 2023 · 6 comments · Fixed by #3657
Assignees
Labels
enhancement New feature or request Task

Comments

@willmcgugan
Copy link
Collaborator

We need a way for Inputs to limit the characters they allow.

A classic use would be to have an Input that only allowed entering numbers.

Have a look at the browser input and see how its done there. Please propose a solution here before attempting.

@1dancook
Copy link
Contributor

My two cents:

HTML form inputs have a number of attributes that can be set. But this approach seems to be like the HTML version of the one ring to rule them all. I can just imagine the spaghetti code trying to implement all of the logic for that.

In order to keep some concerns separate, I'd propose a number of higher level widgets that subclass the Input widget. I'm thinking more in line with how you can set a "type" for an html input. I.e. type="email", type="number" etc. Some widgets that correspond to those html input types could be a good solution. The benefit for developers using textual is that they don't have to roll their own solution to something commonly used. It also makes it very quick and clean to compose forms.

Some ideas:

An NumberInput(Input) could validate each character (on_key). If it matches a digit or period, insert it, otherwise ignore. Flag to limit to integers.

An EmailInput(Input) could validate that the entire input is a valid email string on submission.

A URLInput(Input) like the above but for a URL.

A TelephoneInput(Input) should limit input characters to [0-9]|-. (Validating whole phone numbers for all cases worldwide is probably crazy -- you could have a valid phone number in Japan but it's not valid in USA where it needs to be used). Probably best to leave full number validation up to the developer.

A PasswordInput(Input) would make the password parameter of input obsolete.

A DateInput(Input) not to be confused with a DatePicker. Only allow digits, hyphens, slashes. Submission validation would probably be best left to developers.

Depending on the widget above, some other parameters could make sense. For example a NumberInput could take a maxlength, etc.

There is also the pattern attribute for html input which appears to take a regular expression. This seems to check the input on submission. This behavior can already be implemented with validators in textual.

Possibly related: with textual-web corresponding something like NumericInput to <input type="number"> so that the right keyboard layout pops up for mobiles (this is a thought out of ignorance for how textual-web actually works because I haven't looked yet 😅)

@davep davep added enhancement New feature or request Task labels Oct 12, 2023
@MorningLightMountain713

This would be a great feature. As part of limiting input characters, is it possible to add limits on input length. A use case would be for day/month/year fields.

Also preventing input entirely. I have subclassed Input for this, and just blink the cursor if input prevented.

Limiting characters would be a great addition as you can then deal with unwanted input as it happens, prior to validation.

Would be good to be able to use a pattern (regex) to build an input that validates on a per key basis - you could then implement all of the above just based on different regexes. (except password) - the regex could also limit the length.

@davep davep self-assigned this Oct 26, 2023
@davep
Copy link
Contributor

davep commented Oct 26, 2023

Grabbing for initial option evaluation.

@davep
Copy link
Contributor

davep commented Nov 8, 2023

A wee wander through some of the pre-existing approaches and things to consider.

Introduction

I feel there's a couple of things that need to be considered with this, and that they often go hand-in-hand. Restricted inputs tend to also imply formatted inputs; the idea being that someone seldom wants to say "I want to only allow input of numbers" but instead wants to say "I want to allow entry of a floating point value up to 3 decimal places", etc; this would normally imply that they want to be able to say that the input should be of a specific format when the user types. Moreover, it's not uncommon to have the format characters (in the case of the decimal, it would be a . or , depending on locale) be an active but fixed part of the input; that is to say: the developer may want a field that is of the format 9999.99 and when the user types 3. the cursor will move to after the . so the developer can carry on typing the decimal places (it would also likely need to be that the . does the correct locale-dependant thing).

Pre-existing approaches

This isn't exactly a novel problem; there are plenty of frameworks and the like out there that have solved this problem one way or another. Here I'll note the main approaches that seem to exist, from which we might take inspiration.

xBase/Clipper PICTURE strings

While likely a bit of a niche one for some folk, if you were building DOS-based applications in the 1990s (not dissimilar to look and feel to terminal based applications in the 2020s), it was very likely you were doing it with some xBase variant, and more often than not Clipper. Clipper had a very flexible method of restricting and formatting inputs as part of its @ ... GET command.

This took the form of a "picture string".

In short, a picture string would comprise of two optional parts, a picture function and a template. The function part would be at the start of the string and declare general facts about the input (should default input be cleared when the user types, how long should the input be before horizontal scrolling takes place, how negative numbers should be displayed, etc). The template itself would dictate what characters could be typed in what positions, and in some situations would allow specifying specific literal values.

As an example, "9,999,999.99" would allow the user type type in a numeric value with a lower and upper bound, and would permit a sign.

Pros: Generally useful, lends itself well to external configuration, and is easy to follow and understand.

Cons: Not as visually flexible as, say, custom-made input widgets for specific types of data (a calendar for a date, etc).

Web-style input types

"Standard" web input has a system of types. These are in a curious position of, in places, formatting/restricting the input, and in other cases fundamentally changing the type of input control that is used. Consider checkbox or color vs something like email or number.

Pros: Very flexible and can allow the inputs to be very specific to the intended purpose.

Cons: Actually kind of doesn't solve some of the issues this seeks to solve in that, while you can create classes of input widgets, all the problems of restriction and formatting still remain (so a float input might still need to restrict precision or sign, etc). Another downside is that, unless you're careful, you can end up with an inconsistent interface. Yet another downside is that creating subclasses of input can inevitably result in over-restriction: (see the idea of a TelephoneInput mentioned in another comment above).

Web-style input pattern

“Standard” web input has a pattern attribute. This can be very useful and very flexible, but also still not quite in the spirit of what’s intended here.

Pro: Regular expressions can be flexible and powerful.

Cons: Regular expressions can be flexible and powerful. Also, this doesn’t really restrict input, it just provides a way of detecting if given input matches the desired pattern.

Conclusion

Personally, I think there's more than one issue rolled into a single issue here; and perhaps it should be broken out some more. In my own experience of developing terminal-based data entry systems I know that the "picture" approach mentioned above is one of the most flexible I've worked with, and generally solves a lot of the problems that need solving; some of the other problems that need to be solved are already taken care of by the current validation system.

@davep davep removed their assignment Nov 8, 2023
@willmcgugan willmcgugan self-assigned this Nov 9, 2023
@davep
Copy link
Contributor

davep commented Nov 10, 2023

As a small followup to the notes above, prompted by this discussion popping up, this was one of the other benefits of the "picture" approach I mention above with the xBase family of languages: the formatting side of things took care of this (numeric inputs would align in the way you'd expect from a numeric input).

Copy link

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Task
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants