Как заменить элемент на мой виджет 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); (как упоминалось в предыдущем посте)