Есть ли способ получить сгенерированную HTML как строку из объекта UIComponent И правильно связать все ajax прослушиватели в фазе ответа RENDER? - PullRequest
1 голос
/ 19 февраля 2020

Это продолжение этого вопроса .

Среда

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 части (из-за того, как должны быть определены элементы управления (здесь, легенды) - см. Функцию ниже):

  1. a JS фрагмент executeInteractiveLegendScript (со строкой для создания виджета Primefaces) и

  2. и 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, в своем ответе , упомянутое

(при условии, что вы находитесь в фазе вызова приложения; когда вы находитесь в фазе ответа рендеринга, это нужно сделать по-другому):

, что подтверждает, что я делаю что-то не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...