Это продолжение этого вопроса .
Среда
Primefaces 8.0.RC3
JSF 2.2.15
Tomcat 8.5.47
Фон
У меня есть пользовательский компонент JSF, который расширяет UIComponentBase
.
public final class Map extends UIComponentBase implements Widget {
// resolveWidgetVar
// a constructor
// getters/setters
}
Существует MapRenderer
, который будет визуализировать этот компонент.
public final class MapRenderer extends CoreRenderer {
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
final Map map = (Map) component;
encodeMarkup(context, map);
encodeScript(context, map);
}
private void encodeMarkup(FacesContext context, Map map) throws IOException {
// renders a div
}
private void encodeScript(FacesContext context, Map map) throws IOException {
// renders a script with PF.cw(widgetName, widgetVar, cfg)
}
}
Это будет листовка на основе карты с легендой, определенной как SelectManyMenu
компонент. Легенда служит и легендой, и фильтром. Задача состоит в том, чтобы приятно передать все необходимое стороне JS. Для этого я использую подход, показанный этим ответом - я в основном кодирую программно созданный SelectManyMenu
в мой Writer
.
Затем я разделил его на 2 части (из-за того, как должны быть определены элементы управления (здесь, легенды) - см. Функцию ниже):
a JS фрагмент executeInteractiveLegendScript
(со строкой для создания виджета Primefaces) и
и HTML фрагмент getInteractiveLegendHTML
(разметка меню).
function (configuration) {
var interactiveLegend = L.control({position: 'bottomleft'});
interactiveLegend.onAdd = function () {
var container = L.DomUtil.create('div', 'interactive-legend');
container.innerHTML = configuration['getInteractiveLegendHTML']();
return container;
};
interactiveLegend.addTo(map);
configuration['executeInteractiveLegendScript']();
}
configuration
- это объект, который я скомпилировал на стороне Java. В какой-то момент, с помощью JS, я добавляю легенду на карту. Фрагмент JS выполняется правильно, элемент Primefaces отображается правильно - здесь нет проблем.
Проблема
Проблема заключается в определении поведения клиента для этого программно созданного компонента.
// while rendering the map
SelectManyMenu selectManyMenu = (SelectManyMenu) context.getApplication()
.createComponent(SelectManyMenu.COMPONENT_TYPE);
// setting children and properies
selectManyMenu.addClientBehavior("change", createAjax(context));
selectManyMenu.encodeAll(context);
Метод создания ClientBehavior
определяется следующим образом:
private ClientBehavior createAjax(FacesContext context) {
Application application = context.getApplication();
ExpressionFactory expressionFactory = application.getExpressionFactory();
AjaxBehavior behavior = (AjaxBehavior) application.createBehavior(AjaxBehavior.BEHAVIOR_ID);
MethodExpression methodExpression = expressionFactory.createMethodExpression(context.getELContext(), "#{myexpression}", Void.TYPE, new Class[]{String.class});
AjaxBehaviorListenerImpl listener = new AjaxBehaviorListenerImpl(methodExpression, methodExpression, methodExpression);
behavior.setProcess("@this");
// PROBLEM HERE - this listener never gets invoked
behavior.addAjaxBehaviorListener(listener);
return behavior;
}
Я сомневаюсь в том месте, где я регистрирую это поведение клиента, может ли быть так, что уже слишком поздно и слушатель просто не регистрируется должным образом?
Вопрос в том, как заставить его работать, и где я должен создать экземпляр меню и связать все свойства / слушатели.
@ Balus C, в своем ответе , упомянутое
(при условии, что вы находитесь в фазе вызова приложения; когда вы находитесь в фазе ответа рендеринга, это нужно сделать по-другому):
, что подтверждает, что я делаю что-то не так.