Wrapping VTextField and adding content to it (6.8.9)

Hi,

I am trying to extend TextField to add additional div.
When TextField is generated it results in:

and what I am trying to do is:

I have extended VTextField but having problems in atchiving this structure.
Tried:

public VMyTextField() {
super();
Element div = Document.get().createDivElement().cast();
getElement().appendChild(div);
}

which results in:

which is not quite what I want. Is there an easy way to get hold of the TextField enclosing div (

) so I can add my div to it ?

Also - I tried to do something like this:

public VPopupTextfield() {
super(getPopupTextfieldElement());
getElement().setClassName(CLASSNAME);
DivElement e = Document.get().createDivElement();
e.setClassName(POPUP_INDICATOR_CLASSNAME);
getElement().appendChild(e);
}

private static final com.google.gwt.user.client.Element getPopupTextfieldElement() {
com.google.gwt.user.client.Element div = Document.get().createDivElement().cast();
Element textInput = DOM.createInputText();
textInput.setClassName(VTextField.CLASSNAME);
div.appendChild(textInput);
return div;
}

which does exactly what I want but because now TextField is identified with my own top div - events are throwing an exception (tries to run getCursorPos and fails).

Any suggestions highly appreciated.

Thanks,
Adrian

Interesting question. I too have the same problem in the
CSValidation
add-on, where the error label is now added as a

after the element. It would be nice to wrap the in a
. It is inside the
of its containing layout, but that can cause problems. For example, in a CssLayout, the successive divs will wrap.

Indeed, the VTextField assumes that its root element is an . To fix that, you’d need to override quite many methods there, and I hope none of them are private. Its a bit annoying task and can’t be done in an extension.

You can get the parent

of the with DOM.getParent().

The following does the same thing in a TextField extension (in CSValidatorConnector):


VTextField field;

@Override
protected void extend(ServerConnector target) {
    field = (VTextField) ((ComponentConnector)target).getWidget();
}

... Then when you need it:
Element textbox = DOM.getParent(field.getElement());
Element messageElement = DOM.createDiv();
DOM.insertChild(textbox, messageElement, DOM.getChildIndex(textbox, field.getElement()) + 1);

You can’t use appendChild() there, as there could be some other elements after the , and you want to insert it immediately after that.

I’m not sure what you are doing, but I recommend modifying the behaviour of TextField with a component extension instead of…extending it.

One way to wrap the TextField inside an element is to wrap it inside a CustomField on the server-side. I have a similar solution in the
Revolution add-on
, albeit for an Image component wrapped in a CustomComponent. The problem is that you’ll have to delegate the TextField API to the wrapped component, which can be a huge task if you want to delegate all of it. And, it won’t be a subclass of TextField, if you want that.

Well, if you want to go with wrapping, it would probably be cleanest to do on the client-side with a connector that maybe extends TextFieldConnector, and overrides getWidget() to create the VTextField widget, wrap it in maybe FlowPanel, and then return the VTextField inside the wrapper… I’m not sure if that would work.

Hi Marko,

Thanks very much for your reply.

I actually got it working yesterday night with the original approach I had
which is this:

public VPopupTextfield() { super(getPopupTextfieldElement()); getElement().setClassName(CLASSNAME); DivElement e = Document.get().createDivElement(); e.setClassName(POPUP_INDICATOR_CLASSNAME); getElement().appendChild(e); }

private static final com.google.gwt.user.client.Element getPopupTextfieldElement() {
com.google.gwt.user.client.Element div = Document.get().createDivElement().cast();
Element textInput = DOM.createInputText();
textInput.setClassName(VTextField.CLASSNAME);
div.appendChild(textInput);
return div;
}

And yes - you are right - I had to override quite a few methods from ValueBoxBase class
where it performs all actions using getElement() which obviously is not tied to text input
anymore. One thing I could not overcome was to properly override methods using AutoDirectionHandler
as it would require to extend a lot of classes and in fact I dont need it as the app is only going to be
used in UK :slight_smile:

Thanks a lot,
Adrian