PDA

View Full Version : Setting max length on TextField



icfantv
2 Feb 2012, 10:20 AM
Is there really no way to set the max length on a text field? I know I can use a max length validator but that doesn't prevent the user from entering more characters than is "allowed."

There was a setMaxLength(...) in 2.x on the TextField object. Why was it pulled in favor of a validator?

PhiLho
3 Feb 2012, 2:14 AM
An obvious solution would be to set the maxlength attribute on the underlying input element, but I wasn't sure how to do it.
I found a solution in a blog post:
http://www.selikoff.net/2011/04/26/gwt-bounded-textfield-in-gxt/

icfantv
3 Feb 2012, 8:18 AM
Yes, that is an obvious solution indeed. :-) How to actually get to the DOM element is the tricky part.

Thanks for that post. The solution I thought of (but was dreading) was something we had to do back in my Java Swing days which was to add a key up listener to the field and when the limit was hit, stop allowing input. But it's annoying because you still have to allow for the backspace and delete keys.

I will use your posted solution. Thanks again.

icfantv
14 Mar 2012, 4:15 PM
Just getting back to this.

In case anyone sees this in the future, here's what I've come up with - not sure if it's the "right" way, but it passes the smell test to me:

public class BoundedTextField extends TextField {


public BoundedTextField() {
this(100);
}


public BoundedTextField(int maxLength) {


super();
if (maxLength <= 0) {
throw new IllegalArgumentException("the max length must be positive: " + maxLength);
}


this.maxLength = maxLength;
this.addValidator();
}


@Override
public void onAfterFirstAttach() {


XElement element = this.getInputEl();
element.setAttribute("maxlength", Integer.toString(this.maxLength));
}


private void addValidator() {
this.addValidator(new MaxLengthValidator(this.maxLength));
}


private final int maxLength;
}

dardison
19 Mar 2012, 7:26 AM
Hi,

I would like to know what Sencha Team have to say about the issue.
Anyone?

SelzChi
17 Apr 2012, 3:42 AM
Hi,

any news regarding this issue?

Thanks,

Selcuk

Thunders
16 Jun 2012, 6:00 AM
There is a way to set max length on a textfield.it passes the test to me.
like this:

public class MyTextField extends TextField {

public MyTextField(){
InputElement ie=this.getInputEl().cast();
ie.setMaxLength(10);
}


}

nbuesing
6 Nov 2012, 10:27 AM
This should be made part of the TextField API, is there any reason Sencha is avoiding adding something a common place as this functionality with their components?

Colin Alworth
6 Nov 2012, 2:25 PM
Short answer: There are good solutions already presented here - I can agree that this looks like a useful feature to add, but one that can be added without requiring that the library itself be modified. We aren't avoiding this, but it isn't quite as straightforward as just adding a setter method in the TextField class.

Really long answer (with my apoligies: once I got going on the topic, I apparently couldn't stop):
As to why we haven't made the change ourselves: From the perspective of users only directly manipulating the Widgets that extends TextField, its pretty easy - you just want a setter that modified this dom attribute so the browser takes care of it for you.
From an API perspective, this feature belongs in the ValueBaseField class, the root class from which TextArea, ComboBox, TextField, etc are started - these all have an InputElement somewhere in them that can be manipulated, or something very much like it.

Then you think about the Cells - really, most of the ValueBaseInputCells should support this so that they can be added directly to a ColumnConfig in a Grid/TreeGrid, a Tree, a ListView, or any Cell Widget in GWT itself. Since there isn't any logic typically involved, it truly does belong in the cell - its just details of how to put the elements and attributes on the page - no real Widget logic required. So we add it in the appropriate place in that type tree, and methods that allow it to be set from the Fields themselves.

But (anyone see yet where I'm going?) the DOM manipulation in a modern, re-themeable GWT library doesn't belong in either the Widget or the Cell subclasses. This kind of direct manipulation really belongs one step lower - the appearance, directly responsible for all initial drawing and updates, as well as checking for where events have occurred, and if they have a special meaning. So we move it there, and modify the API accordingly for all ValueBaseFieldAppearance subtypes. And this means that anyone who is building custom appearances for their own organization needs to go through and update all of their appearances for textfield, textarea, combobox, spinnerfield, datefield, numberfield, etc, whether or not they even use this feature.


API changes can't be taken lightly, and we've already been perhaps too abusive with our changes - even when we document them, there are several organizations that use GXT with their own internal themes that need to rebuild their appearances to fit our extra methods, arguments, etc. Likewise, we can't just add these new features where they will probably be used (i.e. in TextField itself), or we'll be hearing about the 'bad code smell' from anyone who has a NumberField or a ComboBox and wants this.


As with most interesting problems out there, if it was easy, we probably would have done it, or are just not aware of it. This is the Q&A forum, not Discussion, not Feature Requests, so some amount of latitude could perhaps be granted there as well. Okay - so long-winded abstraction rant out of the way, the feature itself:

First, my references for this:
[1] https://developer.mozilla.org/en-US/docs/HTML/Element/Input#attr-maxlength
[2] http://wufoo.com/html5/attributes/03-maxlength.html

MDN apparently indicates that this is a HTML5 feature [1], which makes me concerned that not all browsers will support this. I then tested a demo [2] in IE8, and found that while the <input> behaved as expected, the <textarea> did not. So for some browsers, our Cell will need event handlers specific to this, trying to make the behavior consistent.

Back to the demo [2] - this page indicates that Opera, which GXT supports, has an alternative implementation. Apparently instead of preventing the user from typing, an in-browser tooltip appears, warning the user that the entered (or pasted! there is another test case to have to handle, in all browsers...) text is too long and should be cut down.


So we're not avoiding this because we're lazy - we're targeting the bugs that are affecting users, and adding the features that won't break existing builds (at least for bugfix releases, 3.1 again may change some APIs), and we've got to take much more care with all browsers and all features than the answers provided in this section. If someone puts together a full solution dealing with all the addressed concerns (that I came up with testing two browsers and writing this in 20 minutes) and would like to sign a CLA to have it contributed, that is more than reasonable - it is welcomed!


Commonplace? Yes. Easy? No. Avoiding? No. No one wins if we just pepper in new features halfbaked and poorly executed, especially while we have a community that can present workarounds, as has happened here.

nbuesing
8 Nov 2012, 8:00 AM
Thanks for the feedback/information, quite helpful.

I am not a fan of a work-around being considered the solution to a problem by a vendor, since that means I may have to come up with another work around (or worse yet it fails to work completely) with a new release (including a simple bug-fix release) of the product. That being said, there is more to take into account, based on all the feedback you provided.

progmate
5 Mar 2013, 6:23 AM
I achived maxlength through ComponentPlugin.
I don't like to extend controls.
Did not yet decided which way is better.



public class MaxLengthComponentPlugin implements ComponentPlugin<ValueBaseField<?>> {
int maxLength = -1;
public MaxLengthComponentPlugin(int maxLength) {
this.maxLength = maxLength;
}
@Override
public void initPlugin(final ValueBaseField<?> component) {
if (component.isRendered() && maxLength > 0) {
getInputEl(component).setAttribute("maxLength", "" + maxLength);
}
component.addAttachHandler(new AttachEvent.Handler() {
@Override
public void onAttachOrDetach(AttachEvent arg0) {
if(maxLength > 0) {
getInputEl(component).setAttribute("maxLength", "" + maxLength);
}
}
});
}
protected XElement getInputEl(ValueBaseField<?> component) {
return XElement.as(component.getCell().getInputElement(component.getElement()));
}
}

traviter
8 Aug 2013, 12:46 PM
The workaround on setting on the InputElement does not seem to work. I assume this is because the input element is overwritten every time the cell is rendered.

I delved down the Cell/Appearance rabbit hole and managed to get maxlength working with some very messy render overrides. This is definitely something that just belongs in the API.

The key would be adding maxlength to the FieldAppearanceOptions (or more correctly - a new text-specific subclass since this shouldn't affect some fields such as checkboxes). If the change is made there, it won't break anyone's existing code because it just adds getters and setters for maxlength on the options, cells, and fields. The default cell and appearance render methods would need to be updated to call setMaxLength() and getMaxLength() respectively to/from the FieldAppearanceOptions. But this still doesn't break anyone with custom cells and appearances. Even entirely custom render methods will still work - they just won't support maxlength without an update. So yes, you're still getting the "bad code" smell in that regard, but there's not much you can do to stay in sync when such a large and fundamental piece such as render() has to be overridden. Anyone who does so should know that changes at that level carry a certain level of risk and technical debt. Hence, this is why I'd like to reduce my own risk, and just see it in the API.

In any case, those are my thoughts. I can probably contribute code if I can get set up to do so.

icfantv
8 Aug 2013, 1:48 PM
@traviter, we've been using the input element solution for several years now from beta2 to 3.0.5 and haven't had any issues.

It is possible that the way you are setting the max length attribute is being clobbered by a re-render. This could happen if you are doing it programmatically at some point in your code that would allow this behavior to occur.

As Colin noted, there are several (and I count at least three) solutions that work in this thread. Surely one of them will work for you. If not, please post your code and we would be happy to try and assist you further.

Colin Alworth
8 Aug 2013, 4:16 PM
I'm not going to touch on the feasibility of the current solutions /workarounds without a code sample that follows one of those paths and *doesnt* work correctly (icfantv seems to be better versed than I on them anyway), but I wanted to comment again on including a solution in GXT itself. If you wish to propose a solution, make sure it works cross browser, and not just in one or two widgets - someone will eventually point out that the feature definitely needs to work in IE 6-8 and opera, and definitely needs to work on TextArea as well as TextField. Quoting from myself earlier in this thread:


First, my references for this:
[1] https://developer.mozilla.org/en-US/...attr-maxlength (https://developer.mozilla.org/en-US/docs/HTML/Element/Input#attr-maxlength)
[2] http://wufoo.com/html5/attributes/03-maxlength.html

MDN apparently indicates that this is a HTML5 feature [1], which makes me concerned that not all browsers will support this. I then tested a demo [2] in IE8, and found that while the <input> behaved as expected, the <textarea> did not. So for some browsers, our Cell will need event handlers specific to this, trying to make the behavior consistent.

Back to the demo [2] - this page indicates that Opera, which GXT supports, has an alternative implementation. Apparently instead of preventing the user from typing, an in-browser tooltip appears, warning the user that the entered (or pasted! there is another test case to have to handle, in all browsers...) text is too long and should be cut down.


So we're not avoiding this because we're lazy - we're targeting the bugs that are affecting users, and adding the features that won't break existing builds (at least for bugfix releases, 3.1 again may change some APIs), and we've got to take much more care with all browsers and all features than the answers provided in this section. If someone puts together a full solution dealing with all the addressed concerns (that I came up with testing two browsers and writing this in 20 minutes) and would like to sign a CLA to have it contributed, that is more than reasonable - it is welcomed!


Commonplace? Yes. Easy? No. Avoiding? No. No one wins if we just pepper in new features halfbaked and poorly executed, especially while we have a community that can present workarounds, as has happened here.

fasfsfgs
21 Aug 2013, 1:57 PM
I was using NumberField and I wanted this maxLength feature like you all do.

My solution (all working so far) is this:



new NumberField() {
@Override
public void setMaxLength(int m) {
super.setMaxLength(m);
if (rendered) {
getInputEl().setElementAttribute("maxLength", m);
}
}

@Override
public void onRender(Element target, int index) {
super.onRender(target, index);
getInputEl().setElementAttribute("maxLength", getMaxLength());
}
};