JSF commandLink, созданный программно внутри таблицы, не работает

Это возможно? После нескольких часов боя я сдаюсь.

Таблица JSF создается программно, а внутри commandLinks.

Ниже фрагмент кода с commandLink снаружи и внутри таблицы. Оба создаются аналогичным образом. Полный код XHTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html" xmlns:f = "http://java.sun.com/jsf/core">

<f:view contentType = "text/html" locale = "pl">
    <h:body>
        <h:form id = "form">
            <h:dataTable binding = "#{dynamicDataTable.table}" value = "#{dynamicDataTable.tableContent}" />
            <!-- this one below works fine -->
            <h:commandLink binding = "#{dynamicDataTable.link}" />
        </h:form>
    </h:body>   
</f:view>
</html>

Бин DynamicDataTable:

@Named
@ViewScoped
public class DynamicDataTable implements Serializable {

    private static final long serialVersionUID = 1L;

    private HtmlDataTable table;
    private HtmlCommandLink link;
    private List<String> tableContent;

    public void action() {
        System.out.println("Action performed");
    }

    public HtmlDataTable getTable() {
        table = new HtmlDataTable();
        HtmlCommandLink inlink = new HtmlCommandLink();
        inlink.setValue("Inside link");
        inlink.setActionExpression(createMethodExpression("#{dynamicDataTable.action}", String.class));
        UIColumn column = new UIColumn();
        column.getChildren().add(inlink);
        table.getChildren().add(column);
        return table;
    }

    public List<String> getTableContent() {
        tableContent = new ArrayList<String>();
        tableContent.add("a");
        tableContent.add("b");
        return tableContent;
    }

    public void setTableContent(List<String> tableContent) {
        this.tableContent = tableContent;
    }

    public void setTable(HtmlDataTable table) {
        this.table = table;
    }

    public HtmlCommandLink getLink() {
        link = new HtmlCommandLink();
        link.setValue("Outside link");
        link.setActionExpression(createMethodExpression("#{dynamicDataTable.action}", String.class));
        return link;
    }

    public void setLink(HtmlCommandLink link) {
        this.link = link;
    }

    public static MethodExpression createMethodExpression(String expression, Class<?> returnType) {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getApplication().getExpressionFactory().createMethodExpression(
                context.getELContext(), expression, returnType, new Class[0]);
    }
}

Ссылки внутри таблицы создаются, но не работают. Созданный вне таблицы, также созданный программно, отлично работает.

Любая идея?

В конце концов, это также зависит от того, как вы используете и вызываете это. Предоставьте что-нибудь поддающееся тестированию/проверке в соответствии с минимальный воспроизводимый пример.

Adam Waldenberg 20.01.2019 10:02

@AdamWaldenberg Я обновил свой пример с полным минимальным кодом

robson 20.01.2019 23:30

Я посмотрю.

Adam Waldenberg 21.01.2019 18:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
131
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Краткое объяснение

Проблема, с которой вы столкнулись выше, вызвана тем фактом, что обработчик представления имеет значение не могущий для обработки вашей ссылки действия, потому что он не может сгенерировать идентификатор для компонента ссылки, что означает, что ссылка на активированный компонент фактически отсутствует.

Оба ваших примера на самом деле не совсем верны. Однако со ссылкой, сгенерированной вне таблицы, обработчик представления каким-то образом может определить идентификатор компонента и оказывается в нужном месте при выполнении действия.

Глядя на код

Если мы посмотрим на то, что генерирует JSF Mojarra, когда мы вызываем приведенный выше код, мы увидим следующее:

Ссылки внутри таблицы получают ссылку на form:j_idt3:0:j_id3, но компоненту не присвоен идентификатор, поэтому ссылка не будет работать.

Ссылка вне таблицы получает ссылку на form:j_idt5, и генерируется идентификатор j_id1:javax.faces.ViewState:0. Таким образом, хотя он действительно вызывает действие, корреляция ссылка/идентификатор не совсем верна.

Таким образом, ясно, что рендерер может определить сгенерированный идентификатор для ссылки, но он никогда не устанавливает этот сгенерированный идентификатор на фактический компонент/тег. Это некоторая проблема.

Решение проблемы

Решение здесь состоит в том, чтобы помочь JSF и обработчику представления выяснить путь к компоненту с действием. Вы можете сделать это, принудительно установив идентификатор при программном создании командной ссылки — внутри метода getTable() добавьте следующий код;

inlink.setId("link");

Это должно позволить средству визуализации отображать действительную страницу с рабочими ссылками действий.

Спасибо, это действительно решило проблему (по крайней мере, с h: commandLink). Когда я превратился в Primefaces - он снова не работает. Может из-за включенного ajax. Я постараюсь решить это. Это была отличная поддержка, спасибо.

robson 23.01.2019 14:15

Другие вопросы по теме