简体   繁体   English

JSF PrimeFaces在dataTable中的inputText

[英]JSF PrimeFaces inputText inside dataTable

JSF-2.0, Mojarra 2.1.19, PrimeFaces 3.4.1 JSF-2.0,Mojarra 2.1.19,PrimeFaces 3.4.1

Summary of the problem : Have a p:inputText inside p:dataTable and inputText action fired by p:remoteCommand which passes the dataTable row index as a parameter with f:setPropertyActionListener . 问题摘要 p:inputTextp:dataTable有一个p:inputTextp:remoteCommand触发了inputText操作, p:remoteCommand dataTable行索引作为参数传递给f:setPropertyActionListener But it always passes the last row of the dataTable, not the index of the row which includes currently clicked p:inputText . 但它总是传递dataTable的最后一行,而不是包含当前单击的p:inputText的行的索引。


As it can be seen from my previous questions, I am trying to use p:inputText as a comment taker for a status like in Facebook or etc. Implementation includes a p:dataTable . 从我之前的问题中可以看出,我正在尝试使用p:inputText作为Facebook等等状态的评论接受者。实现包括p:dataTable It's rows represents each status. 它的行代表每个状态。 Seems like: 似乎:

<p:dataTable id="dataTable" value="#{statusBean.statusList}" var="status"
                     rowIndexVar="indexStatusList">
    <p:column>
        <p:panel id="statusRepeatPanel">
            <p:remoteCommand name="test" action="#{statusBean.insertComment}"
                update="statusRepeatPanel">
                <f:setPropertyActionListener 
                    target="#{statusBean.indexStatusList}"
                    value="#{indexStatusList}">
                </f:setPropertyActionListener>
            </p:remoteCommand>
            <p:inputText id="commentInput" value="#{statusBean.newComment}"
                onkeypress="if (event.keyCode == 13) { test(); return false; }">
            </p:inputText>
        </p:panel>
    </p:column>
</p:dataTable>

Upper code says when the press enter key, fire p:remoteCommand which calls the insert method of the managed bean. 上面的代码表示当按下回车键时,触发p:remoteCommand调用托管bean的insert方法。

@ManagedBean
@ViewScoped
public class StatusBean {
    List<Status> statusList = new ArrayList<Status>();
    public int indexStatusList;
    public String newComment
    //getters and setters
    public void insertComment() {
        long statusID = findStatusID(statusList.get(indexStatusList));
        statusDao.insert(this.newComment,statusID)
    }

Let's debug together; 我们一起调试; assuming there are three statuses shown in the p:dataTable , click in the p:inputText which in the second status(index of 1), type "relax" and press the enter key. 假设p:dataTable显示了三种状态,单击p:inputText ,在第二种状态(索引为1)中,键入“relax”并按Enter键。

In the debug console, it correctly shows "relax", but it finds the wrong status because indexStatusList has the value of 2 which belongs the last status in the p:statusList . 在调试控制台中,它正确显示“放松”,但它找到错误的状态,因为indexStatusList的值为2,它属于p:statusList 的最后一个状态 It must be 1 which is the index of p:inputText that clicked on the dataTable row. 它必须是1,它是点击dataTable行的p:inputText的索引。

I think problem is about p:remoteCommand which takes the last index on the screen. 我认为问题是关于p:remoteCommand ,它接受屏幕上的最后一个索引。


How it works? 这个怎么运作?

Let's imagine there is a p:commandLink instead of p:remoteCommand and p:inputText : 让我们假设有一个p:commandLink而不是p:remoteCommandp:inputText

<p:commandLink action=#{statusBean.insertComment>
      <f:setPropertyActionListener target="#{statusBean.indexStatusList}"
          value="#{indexStatusList}"></f:setPropertyActionListener>

This component successfully passes the indexStatusList as currently clicked one. 此组件成功传递indexStatusList作为当前单击的一个。

Conceptual problem in this solution lies in way how p:remoteCommand works. 此解决方案中的概念问题在于p:remoteCommand工作方式。 It creates JavaScript function whose name is defined in name attribute of p:remoteCommand . 它创建JavaScript函数,其名称在p:remoteCommand name属性中定义。 As you putted this in dataTable it will iterate and create JavaScript function called test as many times as there is rows in this table, and at the end last one will be only one. 当你在dataTable它时,它会迭代并创建名为test JavaScript函数,因为这个表中有行,并且最后一个只有一个。 So, solution can be in appending index at the name of the remoteCommand but that is bad, because you will have many unnecessary JavaScript functions. 因此,解决方案可以在remoteCommand的名称附加索引,但这很糟糕,因为您将拥有许多不必要的JavaScript函数。 Better approach would be to create one function an pass argument to it. 更好的方法是创建一个函数作为pass参数。 So define remoteCommand outside of datatable: 所以在datatable之外定义remoteCommand

<p:remoteCommand name="test" action="#{statusBean.insertComment}" update="statusRepeatPanel">

and call test function like this in your onkeypress event: 并在你的onkeypress事件中调用这样的test函数:

test([{ name: 'rowNumber', value: #{indexStatusList} }])

This will pass rowNumber parameter in your AJAX request. 这将在您的AJAX请求中传递rowNumber参数。 In backing bean's insertComment() method you can read this parameter and do with it anything you want: 在支持bean的insertComment()方法中,您可以读取此参数并使用它执行任何操作:

FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
Integer rowNumber = Integer.parseInt(map.get("rowNumber").toString());

NOTE: as you are updating panel in each row, maybe you can change update attribute of remoteCommand to @parent so this will work for all rows. 注意:如您在每行中更新面板,也许你可以改变update的属性remoteCommand@parent所以这将所有行工作。

EDIT: You can update the specific panel in specific row with following code in Java method: 编辑:您可以使用Java方法中的以下代码更新特定行中的特定面板:

RequestContext.getCurrentinstance().update("form:dataTable:" + rowNumber + ":statusRepeatPanel")

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

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