【问题标题】:ui:repeat add new item not working in first elementui:重复添加新项目在第一个元素中不起作用
【发布时间】:2019-02-19 16:49:02
【问题描述】:

我目前正在尝试通过添加/删除primefaces p:commandButton来做一个简单的输入列表。

我在 Glassfish 4.1.1 上使用 PrimeFaces 6.2Mojarra 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>

使用每个p:commandButtonrendered 属性,我想仅在第一个项目上显示添加按钮,并在除第一个项目之外的所有项目上显示删除按钮(使其不可删除)。

我的问题是,在 添加按钮 上使用 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

我不知道在第一个项目中显示它而不是在其他项目或最后一个项目中显示它会发生什么变化。

【问题讨论】:

  • 那么如果你不使用'rendered'属性所有的按钮都可以工作吗?即使你从例如开始列表中有 10 条记录?由于您从stackoverflow.com/questions/2118656/… 中“违反”了#1 和#8,并且根据会话范围的正确或错误,您可能会违反#6。
  • @Kukeltje 我想让这个例子变得简单,但我忘了把&lt;h:form&gt;标签和&lt;ui:composition放在我的视图中,所以&lt;h:head&gt;标签在模板中。对不起,我更新了。
  • 代码应该是 minimal reproducible example... 尝试不使用模板/组合并将 h:head 发布到此文件中。使用创建minimal reproducible example 的原因是:帮助您缩小问题范围(或者 mybe 甚至解决它)并提供代码让我们有一个清晰明确的帮助基础。另见stackoverflow.com/tags/jsf/info
  • @Kukeltje 对不起,我从头开始重现了我的错误并更新了文件代码。我还添加了我的 JSF 版本和实现。
  • 好的,我今天晚些时候试试看能不能解释一下。感谢您使它成为真正的minimal reproducible example。很有帮助

标签: jsf primefaces jsf-2.2 mojarra


【解决方案1】:

我认为这与&lt;ui:repeat&gt; 标志和命令按钮唯一ID 的生成有关。这种观点可能会变得混乱。添加其他按钮时生成的 ID 会发生变化。另外,引入渲染属性也会改变组件的处理方式。

所以要解决这个问题,我认为您需要重新处理 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 类了吗?我不得不介绍这一点,因为 JavaFX 中定义的 Pair&lt;&gt; 类没有可写键属性 - JSF 在处理输入组件的支持 bean 值时需要可写属性。

坦率地说,由于您面临的问题源自 &lt;ui:repeat&gt; 组件/标签,因此在命令按钮上执行 process="example-form:example-container" 也应该可以正常工作 - 只要确保 &lt;ui:repeat&gt; 包含在处理阶段即可。

【讨论】:

  • 谢谢亚当!连续2个回答,你救了我!顺便说一句,我不知道 Lombok,它在 JEE 开发中是否广为人知/使用?用它构建类看起来真的很简单,也更清晰。
  • 很高兴帮助@robinvrd!是的,Lombok 很受欢迎,不仅在 JEE 开发中,而且在一般的许多 Java 项目中,因为它减少了样板代码,添加了一些很棒的功能并很好地清理了类。就个人而言,我总是在新的 Java 项目中使用它。
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
相关资源
最近更新 更多