Search code examples
gwtgwt-platform

Using GWT Nested Editor causes Type mismatch error


I'm currently trying to get nested Editors working in GWT/GWTP.
I have an example working without nesting (thanks to you guys).
When I try to add a sub-editor to this view, I get this error:

...ContainerEditorDialogView_BinderImpl.java' Line 270: Type mismatch: cannot convert from Element to GroupListEditor

This happens when I try to add the sub-editor like this:

public class ContainerEditorDialogView extends
        PopupViewWithUiHandlers<ContainerEditorDialogUiHandlers> implements
        ContainerEditorDialogPresenterWidget.MyView, Editor<ContainerDto> {
    interface Binder extends UiBinder<PopupPanel, ContainerEditorDialogView> {
    }
    public interface Driver extends SimpleBeanEditorDriver<ContainerDto, ContainerEditorDialogView> {
    }

    @UiField
    TextBox uuid;   
    @UiField
    TextBox name;   
    @UiField
    TextBox groups;
    @UiField
    GroupListEditor groupListEditor;
 ...

This is my GroupListEditor:

public class GroupListEditor extends Composite implements IsEditor<ListEditor<String, GroupItemEditor>> {

  private static StringListEditorUiBinder uiBinder = GWT.create(StringListEditorUiBinder.class);

  interface StringListEditorUiBinder extends UiBinder<Widget, GroupListEditor> {}

  private class StringItemEditorSource extends EditorSource<GroupItemEditor> {
    @Override
    public GroupItemEditor create(final int index) {
      GroupItemEditor subEditor = new GroupItemEditor();
      groups.insert(subEditor, index);
      subEditor.addDeleteHandler(new EditorDeleteEvent.EditorDeleteHandler() {
        public void onEditorDeleteEvent(EditorDeleteEvent event) {
          remove(index);
        }
      });
      return subEditor;
    }    
    @Override
    public void dispose(GroupItemEditor subEditor) {
      subEditor.removeFromParent(); 
    }
    @Override
    public void setIndex(GroupItemEditor editor, int index) {
      groups.insert(editor, index);
    }
  }  

  private ListEditor<String, GroupItemEditor> editor = ListEditor.of(new StringItemEditorSource());

  @UiField 
  FlowPanel pWidget;

  @UiField 
  PushButton bAdd;

  @UiField 
  FlowPanel groups;

  @UiField 
  HTML listName;

  public GroupListEditor() {
    initWidget(uiBinder.createAndBindUi(this));
  }

  public void setName(String s) {
    if (s == null) {
      listName.setHTML("");
    } else {
      listName.setHTML(s);
    }
  }

  @UiHandler("bAdd")
  void onBAddClick(ClickEvent event) {
    add();
  }

  private void add() {
    String s = "";
    editor.getList().add(s);
  }

  @Override
  public ListEditor<String, GroupItemEditor> asEditor() {
    return editor;
  }

  private void remove(final int index) {
    editor.getList().remove(index);
  }

}

and its Layout:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
        xmlns:g="urn:import:com.google.gwt.user.client.ui">
        <g:FlowPanel ui:field="pWidget">
                <g:HorizontalPanel>
                        <g:PushButton text="Add" ui:field="bAdd"/>
                        <g:Cell verticalAlignment="ALIGN_MIDDLE">
                                <g:HTML wordWrap="true">&nbsp;Todos</g:HTML>
                        </g:Cell>
                </g:HorizontalPanel>
                <g:HTML ui:field="listName"/>
                <g:FlowPanel ui:field="groups"/>
        </g:FlowPanel>
</ui:UiBinder> 

And the item editor:

public class GroupItemEditor extends Composite implements LeafValueEditor<String> {

  interface StringItemEditorUiBinder extends UiBinder<Widget, GroupItemEditor> {}

  private static StringItemEditorUiBinder uiBinder = GWT.create(StringItemEditorUiBinder.class);

  @UiField 
  TextBox tbvalue;

  @UiField 
  PushButton bDelete;

  public GroupItemEditor() {
    initWidget(uiBinder.createAndBindUi(this));
  }

  @UiHandler("bDelete")
  void onBDeleteClick(ClickEvent event) {
    fireDeleteEvent();
  }

  private void fireDeleteEvent() {
    //fireEvent(new EditorDeleteEvent());
  }

  public final HandlerRegistration addDeleteHandler(EditorDeleteEvent.EditorDeleteHandler handler) {
    return addHandler(handler, EditorDeleteEvent.TYPE);
  }

  @Override
  public void setValue(String value) {
    tbvalue.setValue(value);
  }

  @Override
  public String getValue() {
    return tbvalue.getValue().trim();
  }

And its layout:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
        xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:p1="urn:import:com.google.gwt.editor.ui.client">
        <ui:style>
                .important {
                        font-weight: bold;
                }
        </ui:style>
        <g:FlowPanel>
                <g:HorizontalPanel>
                        <g:TextBox ui:field="tbvalue"/>
                        <g:HTML wordWrap="true">&nbsp;</g:HTML>
                        <g:Cell verticalAlignment="ALIGN_MIDDLE">
                                <g:PushButton text="X" ui:field="bDelete"/>
                        </g:Cell>
                </g:HorizontalPanel>

        </g:FlowPanel>
</ui:UiBinder> 

EDIT: Here is the ContainerEditorDialogView.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">

    <g:DialogBox modal="true">
        <g:caption>
            <b>Local dialog box example</b>
        </g:caption>
        <g:HTMLPanel>
            Container Settings:
            <table>
                <tr>
                    <td>
                        UUID:
                    </td>
                    <td>
                        <g:TextBox ui:field="uuid" />
                    </td>
                </tr>
                <tr>
                    <td>
                        Container Name:
                    </td>
                    <td>
                        <g:TextBox ui:field="name" />
                    </td>
                </tr>

                <tr>
                    <td>
                        Groups (Editor):
                    </td>
                    <td>
                        <GroupListEditor ui:field="groupListEditor" />
                    </td>
                </tr>

                <tr>
                    <td>
                        Groups:
                    </td>
                    <td>
                        <g:TextBox ui:field="groups" />
                    </td>
                </tr>
                <tr>
                    <td>
                        IMEI:
                    </td>
                    <td>
                        <g:TextBox ui:field="imei" />
                    </td>
                </tr>
                <tr>
                    <td>
                        Type:
                    </td>
                    <td>
                        <g:TextBox ui:field="type" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <g:Button ui:field="okButton">Ok</g:Button>
                    </td>
                    <td>
                        <g:Button ui:field="cancelButton">Cancel</g:Button>
                    </td>
                </tr>               
            </table>            

        </g:HTMLPanel>
    </g:DialogBox>
</ui:UiBinder>

Do you have any idea what might cause this error? All information I could find was about three years old...

Thanks :)


Solution

  • <GroupListEditor ui:field="groupListEditor" />
    

    As you intend this to be a widget, it should have a namespace in front of it, like other widgets do. That namespace should be defined at the top with the package that GroupListEditor lives in. For example, if it was pack.age.to.my.client.widgets.GroupListEditor, then this would look like:

    <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
        xmlns:g="urn:import:com.google.gwt.user.client.ui"
        xmlns:my="urn:import:pack.age.to.my.client.widgets">
    
    ...
    
        <my:GroupListEditor ui:field="groupListEditor" />
    

    You can make the namespace whatever you want it to be, I used 'my' for the sake of example.