6 Replies Latest reply: Apr 30, 2013 9:28 AM by Jonathan Fuerth RSS

Binding ValueListBox with <select/> html tag

Jose Miguel Barone Newbie

Hi ... i'm trying to do a <select/> binding to a ValueListBox.

The project is using Errai UI and Errai Binding.

Bindings of String properties with ListBox and <select/> are working perfect ... the same with basic properties (int, String, ...)

 

But when i try to bind a value with the binder (i do a setModel on the binder) i have a ClassCastException when Errai set the value in the ValueListBox.

 

java.lang.ClassCastException: java.lang.String cannot be cast to xxxxxx (xxxxxx it's the value java class)

 

 

It seems that internally the binder try to do a setValue on the ValueListBox with a String type, not with an object of the value class, but i correctly configured the generics part of the ValueListBox, the  Renderer .... :-(

 

Thanks for any guide about how to resolve this issue.

  • 1. Re: Binding ValueListBox with <select/> html tag
    Jonathan Fuerth Master

    Hi Jose,

     

    I should be able to help you get to the bottom of this if you can provide an example class that demonstrates the problem. Would you please respond with a complete @Templated class (and its corresponding .html file) that exhibits this problem?

     

    Thanks,

    Jonathan

  • 2. Re: Binding ValueListBox with <select/> html tag
    Jose Miguel Barone Newbie

    Ok Jonathan ... i will try to explain the problem, but let me say that it's a simple and plain example.

     

    Here goes the html view:

    <!DOCTYPE html>

    <html>

    <form>

              <label for="tipo">Tipo</label>

              <select data-field="tipoMateriaPrima" id="tipo"></select><br>

     

     

              <label for="nombre">Nombre</label>

              <input id="nombre" type="text" data-field="nombre"><br>

     

              <label for="cantidad">Cantidad</label>

              <input data-field="cantidad" id="cantidad" type="number">

     

              <select data-field="unidadMedida" id="unidadMedida"></select><br>

     

              <label for="lote">Lote</label>

              <input data-field="nroLote" id="nroLote" type="number"><br>

     

     

              <label for="proveedor">Proveedor</label>

              <select data-field="proveedor" id="proveedor"></select>

     

     

              <label for="loteProveedor">Lote del proveedor</label>

              <input data-field="loteProveedor" id="loteProveedor"><br>

     

     

              <label for="factura">Factura</label>

              <input data-field="factura" id="factura"><br>

     

     

              <label for="tercerizacion">Tercerizacion</label>

              <select data-field="tercerizacion" id="tercerizacion"></select><br>

     

     

              <button data-field="submit">Ok</button>

    </form>

    </html>

     

    It´s a pretty simple html, with two select´s, on fields "tercerizacion" and "proveedor" (we're talking a little spanish here )

     

    Ok, then the "controller" class:

     

    @Templated("MateriaPrimaView.html")

    public class MateriaPrimaController extends Composite {

              Logger logger = Logger.getLogger("MateriaPrimaView");

     

              @Inject

              Event<MateriaPrima> event;

              @Inject

              @AutoBound

              private DataBinder<MateriaPrima> dataBinder;

     

              @Inject

              @DataField

              @Bound

              private ListBox tipoMateriaPrima;

     

     

              @Inject

              @DataField

              @Bound

              private TextBox nombre;

     

              @Inject

              @DataField

              @Bound

              private TextBox cantidad;

     

              @Inject

              @DataField

              @Bound

              private ListBox unidadMedida;

     

     

              @Inject

              @DataField

              private TextBox nroLote;

     

              @Inject

              @DataField

              @Bound

              private ListBox proveedor;

     

     

              @Inject

              @DataField

              @Bound

              private TextBox loteProveedor;

     

     

              @Inject

              @DataField

              @Bound

              private TextBox factura;

     

     

              @Inject

              @DataField

              @Bound

              private ListBox tercerizacion;

     

     

              @Inject

              @DataField

              private Button submit;

     

              public MateriaPrimaController(){

      }

     

              }

     

              @PostConstruct

              public void init(){

                        tipoMateriaPrima.addItem("ITEM_1");

                        tipoMateriaPrima.addItem("ITEM_2");

              }

     

              public void setModelInstance(MateriaPrima mp){

                        dataBinder.setModel(mp, InitialState.FROM_MODEL);

                        dataBinder.getModel();

              }

     

              @EventHandler("submit")

              private void submit(ClickEvent e){

                        logger.info("submit");

                        event.fire(dataBinder.getModel());

              }

    }

     

     

    And finally the "App" class:

     

    @EntryPoint

    public class App {

              @Inject

              private MateriaPrimaController mpc;

     

              @PostConstruct

              public void init(){

                        MateriaPrima mp = new MateriaPrima("Materia 1", 5,

                                            UNIDAD_MEDIDA.Kg, new TipoMateriaPrima("ITEM_2"),

                                            new Tercerizacion("Tercerizacion 1"));

     

     

                        mp.setLoteProveedor("345RT");

                        mp.setNroLote(6734);

                        mp.setFactura("A3490");

                        mp.setProveedor(new Proveedor("Proveedor1"));

                        mpv.setModelInstance(mp);

     

                        RootPanel.get().add(mpc);

          }

    }

     

     

    It´s really simply, i want to bound a ComboBox with a list of values, it´s an "all time" feature for programmers.

    I think ... is this the right way with Errai?

     

    Also, continue the good work with the framework, it's awesome.

    Thanks.

  • 3. Re: Binding ValueListBox with <select/> html tag
    Jonathan Fuerth Master

    Hi Jose,

     

    Thanks for taking the time to communicate these details! The real problem is that ListBox doesn't implement HasValue, so Errai's Data Binding feature doesn't know how to set/get the selected item from the combo box, and it also doesn't know how to observe it for changes to the selection.

     

    I've worked with your code and found a clean solution to the problem: you can subclass ListBox and implement HasValue<String> like this:

     

    import com.google.gwt.event.dom.client.ChangeEvent;
    import com.google.gwt.event.dom.client.ChangeHandler;
    import com.google.gwt.event.logical.shared.ValueChangeEvent;
    import com.google.gwt.event.logical.shared.ValueChangeHandler;
    import com.google.gwt.event.shared.HandlerRegistration;
    import com.google.gwt.user.client.ui.HasValue;
    import com.google.gwt.user.client.ui.ListBox;
    
    public class BindableListBox extends ListBox implements HasValue<String> {
    
      public BindableListBox() {
        addChangeHandler(new ChangeHandler() {
          @Override
          public void onChange(ChangeEvent event) {
            ValueChangeEvent.fire(BindableListBox.this, getValue());
          }
        });
      }
    
      @Override
      public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
        return addHandler(handler, ValueChangeEvent.getType());
      }
    
      @Override
      public String getValue() {
        return getItemText(getSelectedIndex());
      }
    
      @Override
      public void setValue(String value) {
        setValue(value, true);
      }
    
      @Override
      public void setValue(String value, boolean fireEvents) {
        int foundIndex = -1;
        for (int i = 0; i < getItemCount(); i++) {
          if (value.equals(getItemText(i))) {
            foundIndex = i;
            break;
          }
        }
    
        if (foundIndex == -1) {
          // didn't find a match. we can add the value.
          addItem(value);
          setSelectedIndex(getItemCount() - 1);
        }
    
        if (fireEvents) {
          ValueChangeEvent.fire(this, value);
        }
      }
    
    }
    

    Once you have this BindableListBox, just change the ListBox injection points in MateriaPrimaController to BindableListBox, like this:

     

              @Inject
              @DataField
              @Bound
              private BindableListBox proveedor;
    

     

    Hope that helps!

     

    -Jonathan

  • 4. Re: Binding ValueListBox with <select/> html tag
    Jose Miguel Barone Newbie

    Jonathan: thanks for the response.

     

    With ListBox it works directly ... but i want to work with the values, not with a string representation of them.

    I mean, it will be more simply and natural to add the values to a gwt component and then ask for the selected value obtained from the user, without the boilerplate of what string is what value in my model.

     

    More precisely ... i want to add the Proveedor values to a list and then obtain which Proveedor was selected for the user ... simple.

    It's different to add the names to the list and then obtain the selected name and "calculate" wich Proveedor corresponds with that name ... appears more procedural against an object model.

     

    What do you think?

     

    Thanks

  • 5. Re: Binding ValueListBox with <select/> html tag
    Jose Miguel Barone Newbie

    Well ... i have it working now

     

    How? ... simple, change it to 2.3.0.CR1 version of Errai.

    Now i can use the ValueListBox binded to <select /> html tags and using objects of my domain, not strings.

    Other thing that matters is to create the equals and hash on the domain classes, without that the combo boxes always appends new values.

     

    Thanks and i hope this can help someone out there.

  • 6. Re: Binding ValueListBox with <select/> html tag
    Jonathan Fuerth Master

    Oh, your solution is even better. I didn't know about ValueListBox!

     

    Thanks for the tip!

     

    -Jonathan