Hi i’m making a custom widget that includes a textfield, a button and select box.
My client side class extends from VOptionGroupBase and implements Field, ClickHandler, KeyPressHandler, ChangeHandler, FocusHandler, BlurHandler.
My client side class includes a VTextField variable called ‘text’.
Now there are 2 problems with trying to update the Textfield from within the servercode when i try to set the inputprompt or the text-value. I do this by following code:
@Override
public void paintContent(PaintTarget target) throws PaintException {
if (inputPrompt != null) {
target.addAttribute("prompt", inputPrompt);
}
// Adds the textfield-content as variable
String value = getFormattedTextValue();
if (value == null) {
value = getNullRepresentation();
}
if (value == null) {
throw new IllegalStateException(
"Null values are not allowed if the null-representation is null");
}
target.addVariable(this, "text", value);
super.paintContent(target);
}
In my client-side code, i have the following:
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
// call to super() to set client and id
super.updateFromUIDL(uidl, client);
// do something usefull with update:
text.updateFromUIDL(uidl, client);
}
This does NOT set the text inside the textfield and also does not set the inputprompt when the textfield is empty. although i’m sure that the variables ‘text’ and ‘prompt’ are in the uidl that is used to call the method ‘text.updateFromUIDL(uidl,client)’.
Does anybody know what i’m doing wrong?
I tried to change the updateFromUIDL inside my component to the following code:
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
// call to super() to set client and id
super.updateFromUIDL(uidl, client);
// do something usefull with update:
if(uidl.hasVariable("text"))
text.setText(uidl.getStringVariable("text"));
}
and then i see that the text-value IS set, but that’s impossible to do for the inputprompt… so i would really like to set using the uidl that is given to the updateFromUIDL from the VTextField…
Sorry it took a while to answer, I was about to but forgot…
Basically, what’s happening here (I think) is that when you call
text.updateFromUIDL , it will call
client.updateComponent which will check if the provided UIDL actually represents a text field, and since it doesn’t (the type mapping is something completely different) it will just quit there.
I recommend that you use an actual TextField instance on the server-side as well, so that the mapping between the different parts, server and client, are the same. So in your
paintContent you should paint the TextFields UIDL as a child UIDL of the main component:
Thanks for the reply.
However, i can not use you recommendation to extend from TextField…Why not? Let’s try to explain
My custom widget is really just a list box, but with some extra features. The most important feature is an extra textfield that is shown just above the list box and next to that textfield a button with the caption ‘search’. Now mainly what the component does is react on when the user clicks the search-button. It then uses the input textfield to populate the list box. So it’s similar to the Select-component that is built in Vaadin, but here the ‘filtering’ is not done client-side, but server-side (on the event of the button that is clicked), so that i don’t have to put all possible items in the list-box, because this would just be too much data…
That’s why i’m extending from AbstractSelect and i need it to be that way, because the main purpose of the custom component is being a ‘select box’, so i want all the features of AbstractSelect (adding items, getting the selected item back, …)
But still, i want to be able to set the text, inputprompt, … of the contained VTextfield…
Would that be possible? Can i somehow avoid the the VTextField checking the UIDL if it is really a textfield…?
Sorry for being a bit unclear: I didn’t mean that you should extend TextField, rather combine it with the other component that you were extending originally. This can be done by extending the CustomComponent, and combining all needed parts there.
Or you could do it the ugly way, and just extend the AbstractSelect as you do now, and add the TextField as a private member there. Then provide necessary methods for setting the text of that field. But seriously, this sounds like a place for a CustomComponent.
And for all the abstract methods, i just call the method for the contained Select-component. One problem: my IDE (NetBeans 6.8) says i need to override the abstract method
But when doing that (and putting the annotation ‘@Override’ in front of it), it says ‘method does not override or implement a method from a supertype’, so i’m stuck :(, because when leaving the method out, or not putting the annotation in front of it, the IDE, again says that i need to implement that abstract method…
This sounds like the IDE is validating the code according to Java 6 (implementations of interfaces can be annotated @Override) but the code is compiled with Java 5, where the @Override annotation is not allowed for methods coming from interfaces.
I don’t know how to fix this in NetBeans, but perhaps this gets you on the right track?
Eventually i got it working by not extending from CustomComponent, but from CustomField and implementing Container, Container.Viewer, Container.PropertySetChangeListener, Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier, Container.ItemSetChangeListener.