【问题标题】:JSF Datatable "elegant" way to edit the content of a rowJSF Datatable“优雅”的方式来编辑一行内容
【发布时间】:2013-10-22 07:24:01
【问题描述】:

EDIT1: 正如 Valentin Jacquemin 所建议的那样,我用一个 List<Entry<String,String>> 实现了它 但是,当我现在更改一个值时,tomcat 会抛出一个错误: 错误信息:

    SEVERE: /bvDesktop_RuleOverviewAddActionNode.xhtml at line 111 and column 115 value="#{paramListKVs.value}": Property 'value' not writable on type java.lang.Object
javax.el.PropertyNotFoundException: /bvDesktop_RuleOverviewAddActionNode.xhtml at line 111 and column 115 value="#{paramListKVs.value}": Property 'value' not writable on type java.lang.Object

以及我的xhtml中的对应行:

<p:dataTable id="paramListKV" var="paramListKVs" value="#{ruleTreeBeanAddActionNode.paramListKV}" editable="true" editMode="cell">
    <p:column>
        <f:facet name="header">List Key</f:facet>
            <h:outputText value="#{paramListKVs.key}"/>
    </p:column>
    <p:column>
        <p:cellEditor id="paramListKVsEditTest"> 
             <f:facet name="header">List Value</f:facet>
             <f:facet name="output"><h:outputText value="#{paramListKVs.value}"/></f:facet>
             --><f:facet name="input"><p:inputText value="#{paramListKVs.value}" style="width:96%" /></f:facet><--
        </p:cellEditor>
    </p:column>
</p:dataTable>

由 --> 和 value="#{paramListKVs.value}" 是否正确。有什么想法吗?


我有一个我能够解决的特定问题,但我觉得我的解决方案更像是一种肮脏的方式。我希望有一种更优雅的方式来做到这一点,但我找不到(搜索过)。所以这是我的问题:

我目前正在创建一个基于规则的框架,用于自动处理某些文件,并且我想让我们的编辑人员能够在一个漂亮且简单的 Web 界面中创建这些规则。 我已经有了所需的网站、数据模型等。然而,一个特殊的问题是,Action-Rule 可以有一个 Set of Properties Key-Value 明智的。我选择TreeMap。现在我希望能够adddeleteedit 代表数据表中的单元格。

Java: 创建动作节点:

@ManagedBean
public class RuleTreeBeanAddActionNode {
...
        private TreeMap<String,String> actionParamMap = new TreeMap<String,String>(); 

        private String paramKeyToAdd = "";

        private String paramValueToAdd = "";

        private int paramKeyIndex;

        private String valueToChange;

        private String keyForInfo;

        private UIComponent datatable;

        public void addKeyValueToMap() {

            if((paramKeyToAdd != null || !paramKeyToAdd.equals("")) && (paramValueToAdd != null) || !paramValueToAdd.equals("")) {
            unusedActionParamKeys.remove(paramKeyToAdd);
            usedActionParamKeys.add(paramKeyToAdd);

            actionParamsAsListKeys.add(paramKeyToAdd);
            actionParamsAsListValues.add(paramValueToAdd);

            actionParamMap.put(paramKeyToAdd, paramValueToAdd);
            actionParamMapEntries = new ArrayList<Entry<Integer, String>>((Collection<? extends Entry<Integer, String>>) actionParamMap.entrySet());
            userSession.setAttribute("actionParamMap", actionParamMap);
            userSession.setAttribute("unusedActionParamKeys", unusedActionParamKeys);
            userSession.setAttribute("usedActionParamKeys", usedActionParamKeys);
            userSession.setAttribute("tempSelectorWorkOn", "");
            userSession.setAttribute("tempRuleId", "");

            userSession.setAttribute("actionParamsAsListKeys", actionParamsAsListKeys);
            userSession.setAttribute("actionParamsAsListValues", actionParamsAsListValues);

            paramKeyToAdd = "";
            paramValueToAdd = "";
           }
        }

        public void setValueToChange(String valueToChange) {
            DataTable dt = (DataTable)datatable;
            String id = String.valueOf(paramKeyIndex);
            Entry<String, String> temp = (Entry<String, String>)dt.getRowData();
            actionParamMap.put((String) temp.getKey(), valueToChange);
    }

        //getter and setter

createActionNode.xhtml

<tr>
    <td>Action Parameter </td>
    <td>
        <p:dataTable binding="#{ruleTreeBeanAddActionNode.datatable}" 
                     rowKey="test" 
                     rowIndexVar="paramKeyIndex" 
                     id="paramKeysValues" 
                     var="params" 
                     value="#{ruleTreeBeanAddActionNode.actionParamMapEntries}" 
                     editable="true" 
                     editMode="cell">
            <p:column id="keys">
                <f:facet name="header">Param Key</f:facet>
                <h:outputText value="#{params.key}"/>
            </p:column>
            <p:column id="values">
                <f:facet name="header">Param Value</f:facet>
                <p:cellEditor id="paramValueEdit">  
                   <f:facet name="output"><h:outputText value="#{params.value}"/></f:facet>  
                   <f:facet name="input"><p:inputText id="evinput" value="#{ruleTreeBeanAddActionNode.valueToChange}" style="width:96%"/></f:facet>  
                </p:cellEditor>  
            </p:column>
        </p:dataTable>
    </td>
</tr>
<tr><td><br/></td></tr>
<tr>
    <td>Param To Value</td>
    <td>
        <table>
            <tr>
                <td>
                    <p:selectOneMenu id="paramKeys" value="#{ruleTreeBeanAddActionNode.paramKeyToAdd}">
                        <f:selectItems value="#{ruleTreeBeanAddActionNode.unusedActionParamKeys}"/>
                    </p:selectOneMenu>
                </td>
                <td>
                    <p:inputText id="paramValue" value="#{ruleTreeBeanAddActionNode.paramValueToAdd}"/>
                </td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <p:commandButton id="addParam" value="+" action="#{ruleTreeBeanAddActionNode.addKeyValueToMap}" update="paramKeysValues,paramKeys,paramValue"/>
                </td>
            </tr>
        </table>
    </td>
</tr>    

我知道我需要返回的不是地图而是条目集,以便数据表可以遍历它。因此,当我在单元格中编辑记录时,函数
#{ruleTreeBeanAddActionNode.valueToChange} 在更改时被调用。但是,要检索实际记录以及地图中要更改的键和值,我必须检查 DatatableUIComponent,检索已编辑的记录,保存地图并重建条目集。
所以我的实际问题是,这是推荐的方式吗?我是否监督了一些能让我的世界变得更轻松的事情?有没有其他人实施过这样的事情?

【问题讨论】:

    标签: java jsf jsf-2 primefaces datatable


    【解决方案1】:

    这是UIData 的文档,任何数据表都是它的子:

    UIData 是一个 UIComponent,它支持数据绑定到一个集合 由 DataModel 实例表示的数据对象,它是当前 该组件本身的值(通常通过 值表达式)。在迭代处理中的数据行期间 数据模型,当前行的对象作为请求公开 var 属性指定的键下的属性。

    因此,正如您所说,您需要一个可迭代对象,以便数据表可以循环遍历它并在构建表时公开每个元素。

    另一方面,您在这里并没有完全利用绑定功能。只需让组件完成其工作并将value=#{ruleTreeBeanAddActionNode.actionParams}actionParams 设置为List 或任何其他supported type。完成后,您的数据表模型将引用您的 ruleTreeBeanAddActionNode.actionParams 元素。您不需要任何其他机制来进行同步。

    另见:

    更新

    我猜你试图使用AbstractMap.SimpleEntry 作为你的列表条目。尽管setValue 不是void 类型,但此类与JavaBean 不兼容。创建您自己的对象来保存行的状态,以便您拥有一个与 JavaBean 兼容的对象,并且 EL 将能够正确解析读/写方法:

    public class Entry{
        private String key;
        private String value;
    
        public Entry(String key, String value) {
            this.key = key;
            this.value = value;
        }
    
        public String getKey() {return key;}
        public String getValue() {return value;}
        public void setKey(String key) {this.key = key;}
        public void setValue(String value) {this.value = value;}
    }
    

    然后在您的支持 bean 中:

    @ManagedBean
    public class RuleTreeBeanAddActionNode {
        private List<Entry> entries;
    
        @PostConstruct
        public void init() {
            entries = new ArrayList<Entry>();
            entries.add(new Entry("foo", "bar"));
        }
    
        public List<Entry> getEntries() { return entries; }
    }
    

    【讨论】:

    • 嗯。问题是我不想使用列表。我想在网站上有地图。拥有一个 Key-Value-List 并着手处理它有点困难。
    • 好的,我想我现在正确地实现了它。两个列表,一个用于键,一个用于值,但我仍然需要自己更改值。我将 onmouseout 与 this.form.submit() 一起使用,然后我的支持 bean 中有两个值,现在我可以更改列表中的值。但我仍然认为这不是最好的方法。不知何故,我无法让它工作,以便自动完成对列表的更改。 :(
    • 我仍然建议你摆脱你的地图。如果需要,只需声明一个新对象(即具有键和值属性的条目)并在您的支持 bean 中提供它们的列表。那么就不需要自己保留同步逻辑了。
    • 我确实将列表实现另外添加到地图中。在我把地图扔掉之前,我想测试一下实现。下一步是实施 K-V 列表。我正在考虑 SimpleEntry。让我们看看我能不能让它工作。但仅对我而言:从技术上讲,如果我只使用一个以 K-V 作为值的列表,那么当我编辑它的一个元素时,应该更新该列表,例如键还是值,对吧?
    • 很遗憾,它不起作用。从原始帖子中查看我的编辑:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2011-08-18
    相关资源
    最近更新 更多