Предобработка / постобработка метода действия компонента из p:remoteCommand внутри составного
У меня есть следующий сценарий:
Составной компонент JSF со сложным JavaScript, который я хотел бы частично обновить с помощью JavaScript, добавив новые значения из компонента поддержки (компонент поддержки страницы, которая использует этот составной компонент, а не компонент поддержки) @FacesComponent
). Я не хочу делать полное обновление, потому что это сложный плагин JavaScript, и он недопустимо сломает UX.
Я получаю значения от компонента поддержки @FacesComponent
используя Primefaces's <p:remoteCommand>
с обратным вызовом, как описано здесь. Лучший метод для передачи данных из компонента Java/JSF2 в компоненты Javascript/jQuery.
Я знаю, что это злоупотребление JSF, но хотел бы инкапсулировать всю функциональность в одном модуле и не связываться с JAX-RS. Если вы можете посоветовать другое хорошее решение, как инкапсулировать такой сложный плагин jQuery (для ясности мы мы говорим о FullCalendar, я знаю, что у Primefaces есть собственная реализация этого компонента, но его функциональность недостаточна для моих требований, поэтому мне нужно было создать свою собственную реализацию), которая тесно связана с обратными вызовами ajax с параметрами, с которыми вы можете поделиться Вот.
Мой вопрос, как обновить значения в компоненте поддержки @FacesComponent
от поддержки бина с помощью JavaScript? В настоящее время я участвую в следующей цепочке событий:
звонит из Javascript
<p:remoteCommand>
с параметрами, которые передаются компоненту поддержки@FacesComponent
будет отправлен позже вAjaxBehaviorEvent
JavaScript:
refreshEvents([ {name:'start', value:start.format()}, {name:'end', value:end.format()} ]);
Код JSF:
<p:remoteCommand name="refreshValues" oncomplete="loadValues()" action="#{cc.refreshLocal()}" process="@this"/>
Параметры, которые я передал, хранятся в компоненте поддержки с помощью
getStateHelper().put(...);
Событие jQuery отправляется из составного компонента с помощью следующего кода JavaScript:
var hiddenField = $(document.getElementById(variables.hiddenId)); hiddenField.trigger("keypress");
В переопределенном методе составного компонента
public void queueEvent(FacesEvent event)
Я добавляю к этомуAjaxBehaviorEvent
свойство, которое я сохранил ранее, на 1-м шаге и отправлю его вперед.Отправленное событие из составного компонента, "захваченного" на странице, где составной компонент вложен и выполнен
process
на этом компоненте:<p:ajax event="refreshEvent" process="@this" listener="#{bean.refreshEvents}"/>
в
#{bean.refreshEvent}
метод я выполняю запрос@EJB
бин и загрузка данных.При обратном вызове с шага 1 снова вызывается
loadValues()
<p:remoteCommand name="loadValues" action="#{cc.getLocalData()}" oncomplete="updateValues(xhr, status, args);"/>
В методе вспомогательного компонента
#{cc.getLocalData()}
Я добавляю параметр обратного вызова, используя:RequestContext.getCurrentInstance().addCallbackParam("param", ...);
функция
updateValues(xhr, status, args)
с шага 5 войти вargs
значения этого параметра и выполняет актуальное обновление.
Итак, мой общий вопрос: возможно ли упростить этот процесс и как?
Спасибо.
1 ответ
Это действительно немного сложнее. Всего 3 ajax-запроса просто выполнить действие и компонент поддержки, передавая данные вперед и назад через состояние просмотра.
Ваша основная цель - объявить метод действия компонента в качестве атрибута составного компонента, который затем должен вызываться <p:remoteCommand>
внутри композита и возвращают желаемый объект модели на основе переданных параметров, предпочтительно с некоторой предварительной и последующей обработкой.
Ты можешь использовать <cc:attribute method-signature>
в составном интерфейсе объявить атрибут выражения метода:
<cc:interface componentType="yourComposite">
<cc:attribute name="eventListener" method-signature="com.example.Entity method(java.lang.String, java.lang.String)" required="true" />
</cc:interface>
Который можно использовать в шаблонном клиенте, как показано ниже:
<my:composite ... eventListener="#{bean.eventListener}" />
public Entity eventListener(String start, String end) {
// ...
return entity;
}
Составная реализация может выглядеть так:
<cc:implementation>
...
<p:remoteCommand name="refreshEvents"
process="@this" action="#{cc.processEventListener}"
oncomplete="updateValues(xhr, status, args)" />
...
</cc:implementation>
#{cc.processEventListener}
метод может получить eventListener
атрибут как MethodExpression
и вызовите его, как показано ниже, вместе с некоторой предварительной и последующей обработкой:
public void processEventListener() {
String start = getRequestParameter("start");
String end = getRequestParameter("end");
// ...
MethodExpression method = (MethodExpression) getAttributes().get("eventListener");
Entity entity = (Entity) eventListener.invoke(getFacesContext().getELContext(), new Object[] { start, end });
// ...
addCallbackParam("param", entityAsJSON);
}
Теперь это всего лишь 1 AJAX-запрос "как обычно".