Как заменить элемент на мой виджет GWT?

Можно ли заменить известный элемент html моим компонентом виджета? (Акцент на слово "заменить", я не хочу помещать виджет в этот элемент.:)

<body>
  <img />
  <div />
  <a id="tmpEl" />
  ...
  <img />
</body>

станет

<body>
  <img />
  <div />
  <div class="gwt-panel">...</div>
  ...
  <img />
</body>

Я пробовал что-то вроде этого...

tmpEl.getParentElement().replaceChild(myPanel.getElement(), tmpEl);

... но результирующие элементы DOM были "глухими", то есть они не получали события щелчка. (Чтобы выполнить эту работу, мне, вероятно, придется вызвать RootPanel.get(). Accept (widget), но этот метод недоступен.)

На секунду я подумал, что HTMLPanel.addAndReplaceElement может быть ответом, но это работает только тогда, когда ваш элемент "placeholder" является (прямым) дочерним виджета HTMLPanel. Это, очевидно, не мое дело.: (

Обратите внимание, что я знаю только идентификатор этого элемента, я его не создаю. Проще говоря: мне нужно точно, что говорит вопрос.

Что касается "DOM-манипуляции на более высоком уровне": я с радостью смогу манипулировать DOM на максимально возможном уровне, если он позволяет мне размещать виджет вместо этого элемента-заполнителя.

Ответ 1

Кажется, что вызов widget.onAttach() после вставки виджета в DOM делает трюк.

class MyWidget extends Composite
{
  ...

  public void attach()
  {
    /* Widget.onAttach() is protected
     */
    onAttach();

    /* mandatory for all widgets without parent widget
     */
    RootPanel.detachOnWindowClose(this);
  }
}

tmpEl.getParentElement().replaceChild(myWidget.getElement(), tmpEl);
myWidget.attach();

Кредит отправляется Андре в Группа Google Web Toolkit.

Я все еще удивляюсь, почему RootPanel.addAndReplaceElement(Виджет, Элемент) не похож на HTMLPanel.addAndReplaceElement(Виджет, Элемент).

Ответ 2

Решение, вероятно, не так сильно отличается от того, что предложил Игорь. Я бы написал что-то вроде этого:

RootPanel rootPanel = RootPanel.get();
Element anchorElement = DOM.getElementById("tmpEl");
Anchor anchor = Anchor.wrap(anchorElement);

rootPanel.remove(anchor);
rootPanel.insert(new HTML("<div class='gwt-panel'>...</div>", 0); 

Ответ 3

Я согласен с markovuksanovic - вы должны рассмотреть DOM-манипуляцию на "более высоком уровне". Например, необходимая функциональность предоставляется через интерфейс InsertPanel, который FlowPanel реализует:

FlowPanel mainPanel = new FlowPanel();
Hyperlink link = new Hyperlink("Something cool");
mainPanel.add(link);
mainPanel.add(new Label("Bla bla"));

// Now we want to replace the first element of the FlowPanel with a TextBox
// We can do that by its index...
mainPanel.remove(0);

// ...or Widget instance
mainPanel.remove(link);

// Now we add a TextBox at the beginning
mainPanel.add(new TextBox(), 0);

Как вы можете видеть, этот код намного читабельнее (по крайней мере для меня), вы не манипулируете DOM напрямую (ссылаясь на идентификаторы и т.д.). Конечно, есть места, где прямая манипуляция DOM выгодна (оптимизация, особенно), но по большей части я бы избегал жонглирования элементами, идентификаторами и т.д.:) (по крайней мере, в GWT)

Ответ 4

Я делаю что-то очень похожее. Я читаю содержимое <div>; используя элементы, найденные в <div>, для создания анимированного меню, которое затем заменяет исходное содержимое. Анимированное меню - это виджет.

Кажется, что работает...

// DisclosurePanel is a widget
DisclosurePanel accordion_panel = processAccordion(accordionElement);
// accordionElement is found in the DOM (it a com.google.gwt.user.client.Element)
// clear what was there
accordionElement.setInnerText("");
// add the widget in
RootPanel.get(accordionElement.getId()).add(accordion_panel);

Ответ 5

Я предлагаю вам попробовать что-то вроде этого...

<body>
  <a id="tmpEl" />
</body>

то где-нибудь создайте виджет (например, виджет textBox)

TextBox tb = new TextBox();

После создания виджета вы можете получить объект DOM с помощью tb.getElement() (я не уверен, что правильное имя метода, но это определенно что-то вроде getElement)

После этого вы можете использовать

Element parent = Document.getElementById('tmpEl').getParent();
parent.removeChild(Document.getElementById('tmpEl'));
parent.appendChild(tb.getElement());

Еще одна вещь, которая делает add(), - это вызов Widget.onAttach() в виджетах, добавляемых в панель. onAttach выполняет некоторую работу, чтобы зарегистрировать виджет для получения событий.

Вы можете попробовать вызвать tb.onAttach(); Также может потребоваться вызвать RootPanel.detachOnWindowClose(tb); (как упоминалось в предыдущем посте)