Pregunta

I necesita insertar una [número de] widgets basados ??en UiBinder en otra, en un punto particular. El widget insertado tiene un diseño algo complicado, por lo que estoy tratando de definirlo en HTML.

referencePanel.add (...) falla con java.lang.IllegalStateException: los padres de este widget de no implementa HasWidgets. No sé a qué widget de los padres que es infeliz - innerPanel o referencePanel.

Si se añade el objeto ReferenceUI a RootPanel, y después se añade a la parte inferior de la página. Pero si se añade a RootPanel primera, entonces hay un Código JavaScriptException 3 (HIERARCHY_REQUEST_ERR) cuando se añade a referencePanel.

¿Alguna sugerencia?

public class AppUIDemo extends Composite {
    @UiTemplate("AppUIDemo.ui.xml")
    interface AppUIDemoUiBinder extends UiBinder<Widget, AppUIDemo> {
    }

    @UiTemplate("ReferenceUI.ui.xml")
    interface ReferenceUIUiBinder extends
            UiBinder<Widget, ReferenceUI> {
    }

    private static AppUIDemoUiBinder uiBinder = GWT
            .create(AppUIDemoUiBinder.class);
    private static ReferenceUIUiBinder refUIBinder = GWT
            .create(ReferenceUIUiBinder.class);

    @UiField
    FlowPanel referencePanel;

    public AppUIDemo() {
            initWidget(uiBinder.createAndBindUi(this));
            ReferenceUI reference = new ReferenceUI(refUIBinder);

            HTMLPanel innerPanel = reference.getRefPanel();
            innerPanel.getElement().setId(HTMLPanel.createUniqueId());
            referencePanel.add(innerPanel);
        }
}

public class ReferenceUI extends Composite {

    interface ReferenceUIUiBinder extends
            UiBinder<Widget,ReferenceUI> {
    }

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


    @UiField
HTMLPanel refPanel;

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

    public CreditReferenceUI(final UiBinder<Widget, CreditReferenceUI> binder) {
        initWidget(binder.createAndBindUi(this));
    }

    public HTMLPanel getRefPanel() {
        return refPanel;
    }
}

ReferenceUI.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"
    xmlns:gwittir="urn:import:com.totsp.gwittir.client.ui">
            <g:HTMLPanel ui:field="referencePanel">
            <table>
            <tr>
                <td>
                    <b>First Name</b></td>
                <td>
                    <b>Last Name</b></td>
                <td>
                    <b>Phone</b></td>
                <td>
                    <b>Fax</b></td>
            </tr>
            <tr>
                <td>
                    <gwittir:TextBox ui:field="referenceFirstName" styleName="input"/></td>
                <td>
                    <gwittir:TextBox ui:field="referenceLastName" styleName="input"/></td>
                <td>
                    <table><tr>
            <td> ( </td> <td>
                <gwittir:TextBox ui:field="referencePhoneAreaCode" styleName="input" maxLength="3"/></td>
                <td> ) </td> <td>
                <gwittir:TextBox ui:field="referencePhoneNumber" styleName="input" maxLength="7"/></td>
            <td> # </td> <td>
                <gwittir:TextBox ui:field="referencePhoneExtension" styleName="input" maxLength="25"/></td>
        </tr></table></td>
                <td>
                     <table><tr>
            <td> ( </td> <td>
                <gwittir:TextBox ui:field="referenceFaxAreaCode" styleName="input" maxLength="3"/></td>
                <td> ) </td> <td>
                <gwittir:TextBox ui:field="referenceFaxNumber" styleName="input" maxLength="7"/></td>
        </tr></table></td>
                </tr>
            <tr>
                <td style="text-align:right">
                    <b>Address: </b> Street</td>
                <td>
                    <gwittir:TextBox ui:field="referenceStreet" styleName="input"/></td>
                <td colspan="2" style="width:50%">
                    <table><tr><td>   City</td>
                    <td><gwittir:TextBox ui:field="referenceCity" styleName="input" maxLength="25"/></td>
                    <td> State </td>
                    <td class="state"><gwittir:TextBox ui:field="referenceState" styleName="input" maxLength="2"/></td>
                    <td> ZIP</td>
                    <td><gwittir:TextBox ui:field="referenceZIP" styleName="input" maxLength="9"/></td></tr></table>
                </td>
            </tr>
        </table>
    </g:HTMLPanel>
</ui:UiBinder>

AppUIDemo.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"
    xmlns:gwittir="urn:import:com.totsp.gwittir.client.ui">
    <g:HTMLPanel ui:field="basePanel">
        <!--  <div id="MainContent">  -->
        <p><h2><b>Application Demo</b></h2></p>

        <g:FlowPanel ui:field="referencePanel">
        </g:FlowPanel>
    </g:HTMLPanel>
</ui:UiBinder>
¿Fue útil?

Solución

Voy a empezar con la revisión, a continuación, pasar a explicar después.

Fijación del problema

La forma más fácil de solucionar este problema es el siguiente. Aquí está el código:

HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(innerPanel);

Reemplazar que con el siguiente código. Tenga en cuenta que sólo la última línea ha cambiado.

HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(reference);

De esta manera, va a agregar el objeto Composite. No habrá ninguna diferencia para el usuario, ya que el HTMLPanel (su innerPanel) se adjuntará directamente en el documento.


Algunos antecedentes

Adición de un widget a un panel complejo

Al agregar un widget a un panel complejo (un panel que tiene más de un widget hijo), cuatro cosas suceden uno tras otro:

  1. El siguiente widget se le dice a sustraerse a su matriz actual
  2. El panel añade el widget a su lista de niños
  3. El panel añade el widget al documento
  4. El siguiente widget se cuenta para fijar el panel como su nuevo padre

Contar una widget para sustraerse a su matriz

Cuando un niño se le dice a sustraerse a su padre, uno de las siguientes situaciones:

  • Si el widget no tiene un padre, que no hace nada
  • Si el widget es el hijo de un panel de instrumentos que HasWidgets, dice el widget del panel para eliminar ese widget
  • De lo contrario, el widget lanza IllegalStateException con el mensaje "padre de este widget de no implementa HasWidgets

Compuesto de widgets

Cuando se llama a initWidget(Widget), padre del widget se establece en el objeto Composite.

El problema

Cuando intenta agregar innerPanel, se dijo a sustraerse a su matriz actual. innerPanel es en realidad la raíz de la plantilla UiBinder. Su padre es un objeto Composite (en concreto, ReferenceUI). El resultado es la excepción que son lanzados, como Composite no implementa HasWidgets y no apoya la eliminación de su artilugio.

Otros consejos

Por desgracia, IIRC no se puede establecer un ID para un widget en el código de UiBinder (creo que se puede sólo para HTML normal). Lo que se quedan con el establecimiento de la correcta identificación a través de someWidget.getElement().setId() (como lo hizo en el código anterior).

Lo que falta ahora, creo, es un marcador de posición (un div, palmo, lo que sea) con el codigo correcto en el HTMLPanel referencePanel, así:

<g:HTMLPanel ui:field="referencePanel">
    <div ui:field="referencePanelInner" />
</g:HTMLPanel>

Y en AppUIDemo:

@UiField
DivElement referencePanelInner;
// ...
public AppUIDemo() {
    // ...
    referencePanelInner.setId(reference.getRefPanelId());
}

... a menos que desee añadir el ReferenceUI directamente en referencePanel - en cuyo caso sólo debe utilizar un FlowPanel:)

PS:. En mi humilde opinión, se debe generar y establecer el identificador único para el ReferenceUI.refPanel de la clase ReferenceUI (y exponer el id) - de ese modo no se juega con "internos" del widget de algunos widgets externos


OK, creo que lo tengo. La excepción IllegalStateException se produce porque está agregando ReferenceUI.refPanel (o ReferenceUI.referencePanel, no sé que es el nombre actual) a AppUIDemo (ReferenceUI obviamente no implementa HasWidgets) - cuando debería ser la adición de todo el ReferenceUI reference compuesta :) I no se sabe por qué lo hizo de esta manera en el primer lugar (tal vez por todo el lío con los ID), pero el código debe ser algo como esto:

public AppUIDemo() {
        initWidget(uiBinder.createAndBindUi(this));
        ReferenceUI reference = new ReferenceUI(refUIBinder);

        referencePanel.add(reference);
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top