0

I'm trying to create a widget that will render its associated value in a format that is not the same as the native value. For example, if the value (in the database) is "abcde" I want to show "ab.cd.e" on the screen, and if the user types "abcde" I would also want to show "ab.cd.e". If the user types "ab.cd.e" then I would want to store just "abcde" in the database. I am doing this within the GWT editor framework. I have attempted to use the advice from this answer: Converting String to BigDecimal in GWT, but I can't get it to work. Here's what I have in the UiBinder file:

<g:TextBox ui:field='myTextBox' width='300px'/>

And in the associated Java unit:

@UiField
TextBox myTextBox;
...
initWidget(binder.createAndBindUi(this));
new MyValueBox(myTextBox);

And here's the definition of the MyValueBox widget:

public class MyValueBox extends ValueBox<String> {

//=========================================================================

public static class MyRenderer extends AbstractRenderer<String> {

private static MyRenderer _instance;

private static MyRenderer instance() {
  if (_instance == null) {
    _instance = new MyRenderer();
  }
  return _instance;
}

@Override
public String render(final String text) {
  // validation is required before doing this!
  return text.substring(0, 2) + "." + text.substring(2, 4) + "."
         + text.substring(4);
}

}

//=========================================================================

public static class MyParser implements Parser<String> {

private static MyParser _instance;

private static MyParser instance() {
  if (_instance == null) {
    _instance = new MyParser();
  }
  return _instance;
}

@Override
public String parse(final CharSequence text) throws ParseException {
  return "parsed string";
}

}

//=========================================================================

public MyValueBox(final TextBox valueBox) {
  super(valueBox.getElement(), MyRenderer.instance(), MyParser.instance());
}

}

As you can see, I'm trying to wrap the TextBox that was created using UiBinder, but I don't see any effect from this. I know that I'm missing something very simple, and that there is a much easier way to accomplish this, but I'm stumped. Thank you for any suggestions!

--Edit--

I eventually decided to use a CellWidget, which had the added advantage that I can use this code in a cell widget (e.g., a DataGrid), in addition to using it on a panel. I have documented my solution here: GWT: A Custom Cell Example

Community
  • 1
  • 1
Andy King
  • 1,632
  • 2
  • 20
  • 29

1 Answers1

1

You are missing to declare your custom Widget in the UIBinder. You need to tie the package to the xml declaration, adding yours to the standard one (called 'g'):

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:myurn='urn:import:mypackage'>

Then you should use your declared urn, and the name of your class when declaring your TextBox in the UIBinder:

<myurn:MyValueBox ui:field='myTextBox' width='300px'/>

======EDIT=====

You should extend ValueBoxBase instead of wrapping TextBox, that way you will get control over the Renderer and the Parser as you intend, now you will be able to use your custom box as a widget from within the UIBinder:

public class CustomText extends ValueBoxBase<String>
{
    public CustomText() {
        super(Document.get().createTextInputElement(),CustomRenderer.instance(),
           CustomParser.instance());
      }

    private static class CustomRenderer extends AbstractRenderer<String>
    {
        private static CustomRenderer INSTANCE;

        public static CustomRenderer instance() {    
            if (INSTANCE == null) {
                INSTANCE = new CustomRenderer();
            }
            return INSTANCE;
        }

        @Override
        public String render(String text)
        {
            return "rendered string";
        }    
    }

    private static class CustomParser implements Parser<String>
    {
        private static CustomParser INSTANCE;

        public static CustomParser instance() {
            if (INSTANCE == null) {
                INSTANCE = new CustomParser();
            }
            return INSTANCE;
        }

        @Override
        public String parse(CharSequence text) throws ParseException
        {
            return "parsed string";
        }

    }
}
amaurs
  • 1,622
  • 1
  • 13
  • 18
  • I'm not clear on how to create the MyValueBox instance - the MyValueBox class has a constructor that takes a single argument, which I can of course remove, but then I still need to invoke the inherited constructor, which takes an `Element` as the first argument ... how do I do that? – Andy King Jul 17 '13 at 01:33
  • Why are you sending a TextBox in your constructor? Can I see the constructor for the MyValueBox? However you can take a look to http://www.gwtproject.org/doc/latest/DevGuideUiBinder.html#Using_a_widget to learn about sending parameters via the constructor. – amaurs Jul 17 '13 at 06:10
  • I am sending the `TextBox` to the constructor in order to wrap the `TextBox` in a widget that has a renderer. I don't see a way to override the rendering on a `TextBox`. – Andy King Jul 17 '13 at 15:40