【问题标题】:Strange bevavior of f:setPropertyActionListener inside ui:repeat and accordionui:repeat 和手风琴内 f:setPropertyActionListener 的奇怪行为
【发布时间】:2019-07-31 18:06:04
【问题描述】:

在 jsf/primefaces(版本 6.2)项目中,我可以轻松地在手风琴中显示记录列表。 所有记录都正确显示。
ui:repeat 中,我有一个p:commandButton 可以使用f:setPropertyActionListener 保存一些文本片段(fragmt)。

我还实现了第二个f:setPropertyActionListener 来获取对象(sRes)。这个工作正常。
但是currentFrag 变量总是会填充最后一个手风琴的文本片段。

<h:form id="accord" >
<p:accordionPanel value="#{myBean.lucSearchResults}" var="sRes" multiple="true">
<p:tab title="#{sRes.score}"> 

    <ui:repeat value="#{sRes.frags}" var="fragmt">
    <h:panelGrid columns="2" cellpadding="10">
        <h:panelGrid columns="1" cellpadding="10">
        <h:outputText value="#{fragmt}" escape="false"/>
        <hr/>
        </h:panelGrid>

        <h:panelGrid columns="1" cellpadding="10">
        <p:commandButton action="#{myBean.saveFrag}" value="Save" >
            <f:setPropertyActionListener value="#{sRes}" target="#{myBean.currentSearchResult}" />
            <f:setPropertyActionListener value="#{fragmt}" target="#{myBean.currentFrag}" />
        </p:commandButton>
        </h:panelGrid>
    </h:panelGrid>
    </ui:repeat>
</p:tab>
</p:accordionPanel>
</h:form>

我在 JSF 和 Java 方面拥有丰富的经验。我对这种奇怪的行为没有任何解释。
非常感谢有关此问题的任何帮助或指示。

【问题讨论】:

    标签: primefaces jsf-2.2


    【解决方案1】:

    我可以使用 Primefaces 7.0、Mojarra 2.3.3、JVM 1.8.0_152-b16、Apache Tomcat 9.0.21、Openwebbeans 2.0.7 重现此示例:

    <h:form id="frm">
        <p:accordionPanel id="accordion" value="#{myBean.cats}" var="cat"
            multiple="true">
            <p:tab id="tab" title="#{cat.name}">
                <ui:repeat var="kid" value="#{cat.kitten}">
                    <h:panelGroup id="group">
                        <p:commandButton id="cmdSubmit" action="#{myBean.doSomething()}"
                            value="submit #{cat.name} - #{kid.name} " process="@form"
                            update=":frm:output">
                            <f:setPropertyActionListener value="#{cat}"
                                target="#{myBean.cat}" />
                            <f:setPropertyActionListener value="#{kid}"
                                target="#{myBean.kid}" />
                        </p:commandButton>
                    </h:panelGroup>
                </ui:repeat>
            </p:tab>
        </p:accordionPanel>
    
        <h:outputText id="output"
            value="#{myBean.cat.name} - #{myBean.kid.name}" />
    </h:form>
    

    这是我的豆子:

    package my.package;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.faces.view.ViewScoped;
    import javax.inject.Named;
    
    @Named
    @ViewScoped
    public class MyBean implements Serializable {
    
        private static final long serialVersionUID = 43L;
    
        private List<Cat> cats;
    
        private Cat cat;
    
        private Cat kid;
    
        @PostConstruct
        public void init() {
            cats = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                final Cat cat = new Cat();
                cats.add(cat);
                cat.setName(String.valueOf(i));
                cat.setKitten(new ArrayList<>());
                for (int j = 0; j < 5; j++) {
                    final Cat kid = new Cat();
                    kid.setName(i + "." + j);
                    cat.getKitten().add(kid);
                }
            }
        }
    
    
        public void doSomething() {
            System.err.println(cat.getName() + " / " + kid.getName());
        }
    
        // getters & setters ...
    
        public static class Cat {
            private String name;
            private List<Cat> kitten;
    
            // getters & setters ...
        }
    }
    

    当击打例如读取“5 - 5.4”的命令按钮输出为“5 - 9.4”:


    将 p:accordion/p:tab 替换为 ui:repeat 时,此示例按预期工作。这表明它与 primefaces 动态选项卡有关并且可能值得报告错误

    process="@form" 替换为process="@this"process="group" 时,它也可以按预期工作并输出按下按钮的正确标签。


    更好的解决方法是使用实现的p:repeat 组件来解决tabView/accordion/dataTable 和不同ui:repeat 实现之间的known incompatibilities

    【讨论】:

    • 标签视图也会失败吗?
    • 是的@Kukeltje
    • 我可以确认,将 process="@this" 放在 commandButton 中它可以按预期工作。非常感谢@Selaron。干得好!
    • @codyLine 我在这里添加了一个提示,以便更好地使用p:repeat 而不是ui:repeat。到现在都不知道这个组件的存在。
    • 酷。我现在也在使用p:repeat