Калитка AJAX + OnComponentTag

Привет, ребята, я хотел добавить событие AJAX на свою домашнюю страницу, но это не работает! Я понял, что если я удалю функцию onComponentTag, она будет работать хорошо. Я понятия не имею, почему это произошло, может быть, вы можете мне помочь! Это мой код:

  final TextField<String> searchInput = new TextField<String>("searchInput", model) {

    @Override
    protected void onComponentTag(final ComponentTag tag) {
     super.onComponentTag(tag);
     tag.put("id", this.getId());
     if (params.getString("search") != null) {
      tag.put("value", params.getString("search"));
     }
    }
   };

   searchInput.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
    @Override
    protected void onUpdate(final AjaxRequestTarget target) {
     System.out.print("never saw that message :(");
     searchInput.setDefaultModelObject("");
     target.addComponent(searchInput);
    }

   });

Большое спасибо за помощь! ТС


person Sylvus    schedule 26.07.2010    source источник


Ответы (2)


Во-первых, вам вообще не нужно переопределять onComponentTag(). Как заявляет seanizer, если вам действительно нужно указать идентификатор разметки самостоятельно, используйте setMarkupId(id). Вы должны понимать, почему рекомендуется, чтобы Wicket управлял идентификаторами компонентов.

Во-вторых, атрибут value, который вы добавляете, не нужен — Wicket добавляет его автоматически для этого компонента. Присвоенное значение является значением объекта модели компонента. См. источник для TextField.onComponentTag().

В-третьих, опять же, как заявляет seanizer, компоненты, которые должны быть обновлены с помощью ajax, должны выводить свои идентификаторы разметки - реализация Wicket ajax использует идентификатор в качестве селектора для элемента. Кроме того, все поведения Wicket ajax, которые расширяют AbstractDefaultAjaxBehavior, автоматически устанавливают outputMarkupId(true) для компонента, к которому они привязаны (см. источник для AbstractDefaultAjaxBehavior.onBind()). Сюда входит AjaxFormComponentUpdatingBehavior.

So:

String id = "searchInput";
final TextField<String> searchInput = new TextField<String>(id, model);
searchInput.setMarkupId(id);

searchInput.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
  @Override
  protected void onUpdate(final AjaxRequestTarget target) {
    System.out.print("never saw that message :(");
    searchInput.setDefaultModelObject("");
    target.setOutputMarkupId(true);
    target.addComponent(searchInput);
  }
});

Наконец, я бы спросил, чего вы на самом деле пытаетесь достичь с помощью такого поведения. Я не вижу причин для передачи этого события на сервер. Конечно, какой-то клиентский JS больше подходит?

person ireddick    schedule 27.07.2010
comment
вы забыли setOutputMarkupId(true) :-) - person Sean Patrick Floyd; 27.07.2010
comment
См. источник для AbstractDefaultAjaxBehavior.onBind() - поведение устанавливает флаг для вас (извините, это неясно - я отредактировал свой ответ, чтобы сделать его более понятным). - person ireddick; 28.07.2010

tag.put("id", this.getId());

это не способ сделать это в калитке.

вместо этого используйте

component.setOutputMarkupId(true)

(либо в конструкторе вашего компонента, либо в методе bind() вашего поведения), чтобы калитка записывала идентификатор, и если вам абсолютно необходимо контролировать, что такое идентификатор (что почти никогда не бывает), вы можете сделать

component.setMarkupId("myId")

Кроме того, вам, вероятно, не следует назначать значение тега самостоятельно, используйте модель (обработка модели чрезвычайно умна в калитке, читайте подробнее о моделях). Существуют допустимые варианты использования onComponentTag, но они выходят далеко за рамки того, что вы делаете. Пусть калитка делает то, что калитка делает лучше всего, и все будет хорошо.


РЕДАКТИРОВАТЬ: ОК, еще одно уточнение

взгляните на исходный код AjaxFormComponentUpdatingBehavior, особенно часть, где создается обработчик событий javascript.

protected final CharSequence getEventHandler()
{
    return generateCallbackScript(
                    new AppendingStringBuffer("wicketAjaxPost('")
                    .append(getCallbackUrl(false)).append(
        "', wicketSerialize(Wicket.$('" 
                         + getComponent().getMarkupId() + "'))"));
}

как видите, калитка использует getMarkupId() для определения фактического идентификатора. Идентификатор, который вы установили с помощью tag.put(id), совершенно неизвестен калитке, и поэтому поведение не может работать.

Стандартная вещь — setOutputMarkupId(true). Это единственный правильный способ указать калитке отображать идентификатор (кроме setOutputMarkupPlaceholder(true), который внутренне вызывает первый метод). Таким образом, вы убедитесь, что id wicket пишет, что id wicket знает о нем. Если это не отображает идентификатор, вы, вероятно, нарушаете какое-то поведение по умолчанию, перезаписывая onComponentTag.

Взгляните на исходный код Component, особенно onComponentTag(), метод, который вы переопределяете:

protected void onComponentTag(final ComponentTag tag) {
    // if(setOutputMarkupId(true) was set)
    if (getFlag(FLAG_OUTPUT_MARKUP_ID)) {

        // set id attribute
        tag.put(MARKUP_ID_ATTR_NAME, getMarkupId());
    }
}

[Комментарии мои. Кстати, это источник древней версии, но я не нашел ни одного актуального источника в Интернете, и функциональность не изменилась.]

Теперь, если, как и в вашем случае, вы хотите установить идентификатор компонента вручную, вы должны использовать

component.setMarkupId("myId")

и конечно

setOutputMarkupId(true)

также. Если это не сработает, перейдите на сайт калитки JIRA и сообщите об ошибке. Но сомневаюсь, это стандартный функционал, который работает у тысяч пользователей.

person Sean Patrick Floyd    schedule 26.07.2010
comment
Извините, но я не могу следить за вами. 1) Я попробовал setOutputMarkupId(true), но он не распечатывает мой идентификатор! Мне нужен идентификатор для моего CSS! 2) Я никогда не хотел менять ID и никогда не буду :) 3) это не решает мою проблему :( Может я просто не достаточно умен :) Пожалуйста, помогите! - person Sylvus; 26.07.2010
comment
см. мой обновленный ответ. вам нужно использовать как setMarkupId(myId), так и setOutputMarkupId(true) - person Sean Patrick Floyd; 26.07.2010