简体   繁体   English

JSF Datatable的“优雅”方式来编辑行的内容

[英]JSF Datatable “elegant” way to edit the content of a row

EDIT1 : As suggested by Valentin Jacquemin i implemented it with one List<Entry<String,String>> however, when i now change a value, tomcat throws an error: error message: 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

And the corresponding line in my xhtml: 和我的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>

marked by --> and <--. 用->和<-标记。 I don't know what java tries to write the code to. 我不知道什么Java尝试将代码编写到。 I'm not even sure if value="#{paramListKVs.value}" is correct. 我什至不确定value="#{paramListKVs.value}"是否正确。 Any ideas? 有任何想法吗?


I have a particular problem i was able to solve, but i feel like my solution is more like a dirty way. 我有一个能够解决的特定问题,但是我觉得我的解决方案更像是一种肮脏的方式。 I hope that there is a more elegant way to do this, but i wasn't able to find one (searched so). 我希望有一种更优雅的方法可以执行此操作,但是我找不到(搜索过)。 So here is my problem: 所以这是我的问题:

I'm currently creating a rule-based framework for automated processing of some files and I want to give our editors the possibility to create those rules in a nice and easy web interface. 我目前正在创建一个基于规则的框架来自动处理某些文件,并且我想让我们的编辑者可以在一个简单易用的Web界面中创建这些规则。 I already have the required websites,datamodel and so on. 我已经有了所需的网站,数据模型等。 However one particular problem is, that an Action-Rule can have a Set of Properties Key-Value wise. 但是,一个特殊的问题是,动作规则可以明智地使用一Set of Properties Key-Value I choose a TreeMap . 我选择一个TreeMap Now i want to be able to add , delete and edit the cells in the representing datatable. 现在,我希望能够adddeleteedit代表数据表中的单元格。

Java: createActioNode: Java:createActioNode:

@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 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>    

I understood that i need to return not the map but the entry set, so that the datatable can iterarte through it. 我知道我不需要返回映射,而是返回条目集,以便数据表可以遍历它。 So when i edit a record in the cell, the function 因此,当我在单元格中编辑记录时,该函数
#{ruleTreeBeanAddActionNode.valueToChange} is called on a change. #{ruleTreeBeanAddActionNode.valueToChange}在更改时被调用。 However to retrieve the actual record and thus the key and value to change in the map, i have to go over the UIComponent of Datatable , retrieve the edited record,save the map and rebuild the entry set. 但是,要检索实际记录以及因此要在地图中更改的键和值,我必须遍历DatatableUIComponent ,检索已编辑的记录,保存地图并重建条目集。
So my actual question is , is this the recommended way? 所以我的实际问题是 ,这是推荐的方法吗? Did i oversee something that would make my world much easier? 我是否监督过一些可以使我的世界变得更加轻松的事情? Has someone else implemented something like this? 有人实施过类似的东西吗?

Here is the doc for UIData , which any datatable is child of: 这是UIData的文档,任何数据表都是其子级:

UIData is a UIComponent that supports data binding to a collection of data objects represented by a DataModel instance, which is the current value of this component itself (typically established via a ValueExpression). UIData是一个UIComponent,它支持将数据绑定到由DataModel实例表示的数据对象的集合,这是该组件本身的当前值(通常通过ValueExpression建立)。 During iterative processing over the rows of data in the data model, the object for the current row is exposed as a request attribute under the key specified by the var property. 在对数据模型中的数据行进行迭代处理期间,当前行的对象作为由var属性指定的键下的request属性公开。

Thus as you said you need an iterable object so that the datatable can loop through it and expose each element when building the table. 因此,正如您所说的,您需要一个可迭代的对象,以便数据表可以遍历该对象并在构建表时公开每个元素。

On the other hand, you're not leveraging on the binding feature completely here. 另一方面,您在这里没有完全利用绑定功能。 Simply let the component doing its job and set value=#{ruleTreeBeanAddActionNode.actionParams} , actionParams being a List or any other supported type . 只需让组件完成其工作并设置value=#{ruleTreeBeanAddActionNode.actionParams}actionParamsList或任何其他受支持的类型 Once done, your datatable's model will reference your ruleTreeBeanAddActionNode.actionParams elements. 完成后,数据表的模型将引用您的ruleTreeBeanAddActionNode.actionParams元素。 You don't need any further mechanism to do the sync. 您不需要任何其他机制即可进行同步。

See also: 也可以看看:

UPDATE UPDATE

I guess you tried to use the AbstractMap.SimpleEntry as entries of your list. 我猜您尝试将AbstractMap.SimpleEntry用作列表的条目。 This class is not JavaBean compatible though as the setValue is not of type void . 此类与JavaBean不兼容,因为setValue的类型不是void Create your own object holding the state of your row so that you've a JavaBean compatible object and EL will be able to resolve the read/write methods correctly: 创建保存行状态的自己的对象,以便您具有与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;}
}

Then in your backing bean: 然后在您的支持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; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM