Действительно ли возможно заменить известный элемент HTML моим компонентом виджета? (Акцент на слово 'заменяет', я не хочу помещать виджет в тот элемент.:)
...
стал бы
...
...
Я попробовал что-то вроде этого...
tmpEl.getParentElement().replaceChild(myPanel.getElement(), tmpEl);
... но получающиеся элементы DOM были 'глухими', т.е. они не получили события щелчка. (Для создания этой работы, я должен был бы, вероятно, назвать RootPanel.get () .adopt (виджет), но тот метод не доступен.)
В течение секунды я думал, что HTMLPanel.addAndReplaceElement мог быть ответом, но который только работает, когда Ваш элемент 'заполнителя' является (прямым) ребенком виджета HTMLPanel. Который является, очевидно, не моим случаем.:(
Обратите внимание, что я только знаю идентификатор того элемента, я не создаю его. Просто помещенный: Мне нужно точно, что говорит вопрос.
Что касается 'управления DOM в более высоком уровне': Я буду счастливо управлять DOM на максимально возможном уровне, если он позволит мне поместить виджет вместо того элемента заполнителя.
Я бы предложил вам попробовать что-то вроде этого...
<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); (как упоминалось в предыдущем сообщении)
Похоже, что вызов 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 group.
Я все еще удивляюсь, почему нет RootPanel.addAndReplaceElement(Widget, Element), аналогично HTMLPanel.addAndReplaceElement(Widget, Element).
Я согласен с марковуксановичем - вам следует рассматривать манипуляции с 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)
Решение, вероятно, не сильно отличается от того, что предложил Игорь. Я бы написал что-то вроде этого:
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);