Команда Primefaces Link работает только на первой странице таблицы данных.

У меня есть столбец с p: commandLink внутри p: dataTable, у которого есть paginator. Когда пользователь нажимает на commandLink, открывается диалоговое окно, отображающее данные этой строки.

HTML-код с данными:

<p:dataTable id="dtSample" value="#{sessionBean.sampleList}"
    binding="#{requestBean.dtSampleList}"
    paginator="true" paginatorPosition="bottom"
    paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
    rowsPerPageTemplate="#{10,25,50}"
    currentPageReportTemplate="({startRecord} of {totalRecords})"
    var="item" emptyMessage="No entries." rows="10" rowKey="#{item.id}">
    <p:column headerText="Id">
        <p:commandLink id="lnkSample"
            action="#{requestBean.onLinkClick(item)}"
            oncomplete="PF('dlgSample').show();"
            update="@(.dialogClass)">
            <h:outputText value="#{item.id}" />
                        </p:commandLink>
    </p:column>
    <p:column headerText="Code">
        <h:outputText value="#{item.code}" />
    </p:column>
    <p:column headerText="Description">
        <h:outputText value="#{item.descr}" />
    </p:column>
</p:dataTable>

Компонент запроса:

public class RequestBean {

    private SessionBean sessionBean;

    private DataTable dtSampleList;

    public void init() {
        // load samle list
        loadSampleList();
    }

    public String onLinkClick(Sample sample) {
        getSessionBean().setSelectedSample(sample);
        return "success";
    }

    private void loadSampleList() {
        List<Sample> list = new ArrayList<Sample>();

        for (int i = 0; i < 100; i++) {
            Sample tmp = new Sample();
            tmp.setId(new BigDecimal(i + 1));
            tmp.setCode("code" + (i + 1));
            tmp.setDescr("desc" + (i + 1));
            list.add(tmp);
        }
        getSessionBean().setSampleList(list);

    }

// getters and setters

}

Сессионный компонент:

public class SessionBean implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<Sample> sampleList;
    private Sample selectedSample;

    // getters and setters

}

HTML-код диалога:

<p:dialog id="dlgSample" closeOnEscape="true" widgetVar="dlgSample"
                    styleClass="dialogClass" modal="true">
    <p:panelGrid columns="1">
        <h:outputText value="Id: #{sessionBean.selectedSample.id}" />
        <h:outputText value="Code: #{sessionBean.selectedSample.code}" />
        <h:outputText value="Description: #{sessionBean.selectedSample.descr}" />
    </p:panelGrid>
</p:dialog>

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

Что я делаю неправильно? Почему метод действия не вызывается ни на одной странице с данными?

Я использую Праймфейс 5.2.


person peterremec    schedule 24.07.2015    source источник


Ответы (3)


Похоже, проблема была в компоненте PF dataTable. Отсутствовали атрибуты first и rows, и после их добавления ссылки на команды на всех страницах работают должным образом.

person peterremec    schedule 11.08.2015
comment
не могли бы вы уточнить это немного подробнее? У меня точно такая же проблема (командные ссылки работают только на первой странице) Мой атрибут «строки» имеет значение «8». Что вы установили для своего атрибута «первый»? - person Christopher Hackl; 22.01.2016
comment
@ChristopherHackl Я связал эти два атрибута со свойствами поддерживающего компонента, например first="#{bean.first}" rows="#{bean.rows}". Таким образом, когда вы нажимаете на другую страницу с данными или изменяете параметр «строк на страницу» с данными, эти свойства компонента обновляются автоматически (не забудьте предоставить геттеры и сеттеры для свойств). Также я инициализировал свойства в поддерживающем компоненте (first = 0, rows = 10). - person peterremec; 22.01.2016
comment
Спасибо за разъяснения! - person Christopher Hackl; 25.01.2016
comment
@ChristopherHackl с удовольствием! - person peterremec; 25.01.2016

Что я делаю неправильно? Почему метод действия не вызывается ни на одной странице с данными?

Распространенная ошибка, приводящая к такому поведению, заключается в том, что ваш state несогласован: для обработки отправки формы JSF воссоздает точно такое же представление, как и в предыдущем запросе, а затем применяет изменения (выполняет действие)

Если это новое представление теперь отличается от представления до отправки, каждое действие прерывается и не вызывается. (Различается с точки зрения задействованных элементов. То есть, если ваша commandLink была rendered="true" перед отправкой, она должна быть rendered="true" во время APPLY_REQUEST_VALUES-этапа).

Итак, из вашего описания я бы предположил, что ваша таблица откатывается на страницу 1, что удалит любую ссылку на странице 2 из представления и прервет действие просмотра, потому что элемент больше не < em>рендеринг.

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

Вы можете легко убедиться в этом, увеличив количество элементов на странице и увидев, что каждая ссылка, перемещенная со страницы 2 на страницу 1, теперь работает.

Но, не видя всего боба, я могу только предполагать это. Для простоты тестирования установите для компонента значение @SessionScoped и посмотрите, решит ли это проблему.

Дополнительные идеи см. в этом сообщении: Метод commandButton/commandLink/ajax action/listener не вызван или входное значение не обновлено

person dognose    schedule 24.07.2015
comment
Проблема была с атрибутами first и rows для dataTable, но все же ваш ответ помог мне думать немного по-другому, поэтому я отметил его как полезный. Спасибо! - person peterremec; 11.08.2015

При размещении таких компонентов, как p:commandLink, в строке p:dataTable всегда следует указывать

process="@this"

Итак, в вашем случае я бы попробовал:

 <p:commandLink id="lnkSample"
        action="#{bean.onLinkClick(item)}"
        oncomplete="PF('dlgSample').show();"
        update="@(.dialogClass)">
        <h:outputText value="#{item.id}" />
 </p:commandLink>

При этом вы уверены, что будет обработан только клик по ссылке, и никакая другая отправка не будет выполнена.

person Ludovic Pénet    schedule 24.07.2015