UI: повторить добавить новый элемент не работает в первом элементе - PullRequest
0 голосов
/ 19 февраля 2019

В настоящее время я пытаюсь сделать простой список ввода с добавлением / удалением простых лиц p:commandButton.

Я использую PrimeFaces 6.2 на Glassfish 4.1.1 с Мохарра 2.2.12 .

ExampleBean.java

package /* myPackage */;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javafx.util.Pair;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named(value = "exampleBean")
@SessionScoped
public class ExampleBean implements Serializable {

    private List<Pair<Integer, Integer>> list;

    @PostConstruct
    public void init() {
        list = new ArrayList<>();
        addNewItem();
    }

    public void addNewItem() {
        list.add(new Pair<>(1, 300));
    }

    public List<Pair<Integer, Integer>> getList() {
        return list;
    }

    public void setList(List<Pair<Integer, Integer>> list) {
        this.list = list;
    }
}

example.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:ui="http://java.sun.com/jsf/facelets" 
      xmlns:p="http://primefaces.org/ui" 
      xmlns:jsf="http://xmlns.jcp.org/jsf">

    <h:head>
        <title>Example</title>
        <meta charset="utf-8" />
    </h:head>

    <h:body>
        <h:form id="example-form">
            <div jsf:id="example-container">
                <ui:repeat value="#{exampleBean.list}" var="item" varStatus="status">
                    <div>
                        <p:inputText value="#{item.key}" />
                        <p:inputText value="#{item.value}" />

                        <p:commandButton 
                            value="Delete" 
                            actionListener="#{exampleBean.list.remove(item)}" 
                            process="@this" 
                            update="example-form:example-container" 
                            rendered="#{!status.first}" />

                        <p:commandButton 
                            value="Add" 
                            actionListener="#{exampleBean.addNewItem()}" 
                            process="@this" 
                            update="example-form:example-container" 
                            rendered="#{status.first}" />
                    </div>

                </ui:repeat>
            </div>
        </h:form>
    </h:body>
</html>

С атрибутом rendered каждого из моих p:commandButton я хочу, чтобы кнопка добавления отображалась только на первом элементе, а кнопка удаления - на всех элементах, кроме первого (делая ее не удаляемой).

Моя проблема в том, что использование rendered="#{status.first}" на кнопке добавления делает все это неработоспособным.

<p:commandButton ... rendered="#{status.last}" /> <!-- actionListener called -->

<p:commandButton ... rendered="#{true}" /> <!-- actionListener called -->

<p:commandButton ... rendered="#{status.first}" /> <!-- actionListener NOT called -->

При rendered="#{status.first}" нажатие кнопки не вызывает actionListener, а вызывает update.

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

1 Ответ

0 голосов
/ 26 февраля 2019

Я думаю, что это связано с флагом <ui:repeat> и генерацией уникальных идентификаторов для командных кнопок.Вид, вероятно, запутался.Сгенерированный идентификатор меняется при добавлении дополнительных кнопок.Кроме того, введение атрибута рендеринга также меняет способ обработки компонента.

Поэтому, чтобы решить эту проблему, я думаю, что вам нужно повторно обработать компонент ui:repeat и кнопки управления, чтобы получить действительные URL-адреса действий.,Решение простое - удалить process="@this".

Я настроил ваш пример с рабочим решением (в примере используется Lombok);

@Data @Named @ViewScoped
public class ExampleBean implements Serializable {

    private List<IntegerPair> list;

    @PostConstruct
    private void init() {
        list = new ArrayList<>();
        addNewItem();
    }

    public void addNewItem() {
        list.add(new IntegerPair(1, 300));
    }

    @Data
    @AllArgsConstructor
    public class IntegerPair {
        private int key, value;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:ui="http://java.sun.com/jsf/facelets"  xmlns:p="http://primefaces.org/ui" 
      xmlns:jsf="http://xmlns.jcp.org/jsf">

    <h:head>
        <title>Example</title>
        <meta charset="utf-8" />
    </h:head>

    <h:body>
        Test!
        <h:form id="example-form">
            <div jsf:id="example-container">
                <ui:repeat value="#{exampleBean.list}" var="item" varStatus="status">
                    <div>
                        <p:inputText value="#{item.key}" />
                        <p:inputText value="#{item.value}" />

                        <p:commandButton 
                            value="Delete" 
                            actionListener="#{exampleBean.list.remove(item)}" 
                            update="example-form:example-container" 
                            rendered="#{!status.first}" />

                        <p:commandButton 
                            value="Add" 
                            actionListener="#{exampleBean.addNewItem}" 
                            update="example-form:example-container" 
                            rendered="#{status.first}" />
                    </div>

                </ui:repeat>
            </div>
        </h:form>
    </h:body>
</html>

Обратите внимание на класс IntegerPair?Мне пришлось представить это, потому что класс Pair<>, определенный в JavaFX, не имеет свойства ключа для записи - свойства JSF требуются для записи при обработке значения вспомогательного компонента входных компонентов.

Откровенно говоря, как проблемавы сталкиваетесь с компонентом / тегом <ui:repeat>, выполнение process="example-form:example-container" на ваших командных кнопках также должно работать нормально - просто убедитесь, что <ui:repeat> включен на этапе обработки.

...