使用AJAX更新JSF / Primefaces数据表中的单行

12

当使用AJAX时,我如何更新p:datatable中的单个行?

我不想更新整个datatable,因为它有很多行,这需要一些时间...

我的布局:

<h:form id="visitForm">
        <p:dataTable id="visitTable" var="visit" value="#{visitBean.findAllVisits()}">

            <p:column headerText="${msgs['email']}"
                <h:outputText value="#{visit.contactDetail.email}"/>
            </p:column>

            <p:column headerText="${msgs['clearance']}" id="clearance">
                <p:commandButton value="${msgs['clearance.ok']}"  actionListener="#{visitBean.makeClearanceNotOk(visit)}"/>
            </p:column>
        </p:dataTable>
    </h:form>

我尝试了一些东西,例如update =“clearance”等,但似乎不起作用。

我正在使用JSF 2.1和Primefaces 5.2


可能是[如何在Primefaces数据表中更新特定行]的重复问题(https://dev59.com/fG_Xa4cB1Zd3GeqPzk95)。 - Bob
4个回答

16
您可以使用@row(n)搜索表达式来更新表中的第n行。要更新当前行,您需要将行索引作为参数传递。在<p:dataTable>上设置rowIndexVar="rowIdx"属性,然后执行以下操作:
<p:commandButton ... update="@form:visitTable:@row(#{rowIdx})" />

1
我已经应用了该指令,但它没有起作用,尽管我正在使用PrimeFaces 6.2和JSF 2.2.18。 - Mohamed Ennahdi El Idrissi
@MohamedEnnahdiElIdrissi,也许我的回答可以帮到你。 - Duloren

10

我不确定我是否迟到了,但是让我就如何使用PrimeFaces的纯ajax功能更新一行内容发表我的意见。

1)部分更新: 我使用PF更新特定行中的某些内容的第一种方法并不是完全更新整个行,而是更新行内感兴趣的区域。这可以通过定义持有面板并更新它们来实现。例如:

<h:form id="testForm">
    <p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}">

        <p:column headerText="id">
            <h:outputText value="#{myEntity.id}"/>
        </p:column>

        <p:column headerText="last update">
            <p:outputPanel id="lastUpdatePanel">
                <h:outputText value="#{myEntity.lastUpdate}">
                    <f:convertDateTime pattern="HH:mm:ss" type="date" />
                </h:outputText>
            </p:outputPanel>
        </p:column>

        <p:column headerText="counter">
            <p:outputPanel id="counterPanel">
                <h:outputText value="#{myEntity.counter}"/>
            </p:outputPanel>
        </p:column>

        <p:column headerText="increment">
            <p:commandButton value="+"
                actionListener="#{myController.increment(myEntity)}"
                update="counterPanel, lastUpdatePanel"/>
        </p:column>
    </p:dataTable>
</h:form>

关键在于更新目标面板(在这个例子中是片段update="counterPanel, lastUpdatePanel")。这会产生类似以下图片的效果:

enter image description here

2) 实际更新行:通常情况下,前面的方法已经足够好用了。但是,如果真的需要更新行,则可以按照之前的回答中给出的建议使用@row关键字:

<h:form id="testForm">
    <p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}" rowIndexVar="rowIndex">

        <p:column headerText="id">
            <h:outputText value="#{myEntity.id}"/>
        </p:column>

        <p:column headerText="last update 1">
            <p:outputPanel>
                <h:outputText value="#{myEntity.lastUpdate}">
                    <f:convertDateTime pattern="HH:mm:ss" type="date" />
                </h:outputText>
            </p:outputPanel>
        </p:column>

        <p:column headerText="last update 2">
            <h:outputText value="#{myEntity.lastUpdate}">
                <f:convertDateTime pattern="HH:mm:ss" type="date" />
            </h:outputText>
        </p:column>

        <p:column headerText="counter">
            <p:outputPanel>
                <h:outputText value="#{myEntity.counter}"/>
            </p:outputPanel>
        </p:column>

        <p:column headerText="increment">
            <p:commandButton value="+"
                actionListener="#{myController.increment(myEntity)}"
                update="@form:myEntityTable:@row(#{rowIndex})"/>
        </p:column>
    </p:dataTable>
</h:form>

诀窍在于将每列内容放入p:outputPanel中,并让update="@form:myEntityTable:@row(#{rowIndex})"完成工作。我故意没有在"last update 2"列中使用outputPanel以说明这一点:

enter image description here

因此,虽然“最后更新1”和“计数器”列在单击“+”后实际上会更新,但“最后更新2”列保持不变。因此,如果您需要更新内容,请使用outputPanel进行包装。值得注意的是,包含每个列内容的输出面板不需要显式ID(如果您想要添加一个,则可以添加)。 为了完整起见,在这些示例中,我使用了PF 6.2。后端bean非常简单:
package myprefferedpackage;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class MyController {

    private List<MyEntity> entities;

    @PostConstruct
    public void init() {
        this.entities = new ArrayList<MyEntity>(10);
        for(int i = 0; i < 10; ++i) {
            this.entities.add(new MyEntity(i));
        }
    }

    public List<MyEntity> getAllEntities() {
        return entities;
    }

    public void increment(MyEntity myEntity) {
        myEntity.increment();
    }

    public class MyEntity {
        private int id;
        private int counter;
        private Date lastUpdate;

        public MyEntity(int id) {
            this.id = id;
            this.counter = 0;
            this.lastUpdate = new Date();
        }

        public void increment() {
            this.counter++;
            this.lastUpdate = new Date();
        }

        public int getId() {
            return id;
        }

        public int getCounter() {
            return counter;
        }

        public Date getLastUpdate() {
            return lastUpdate;
        }
    }
}

正好在我的评论后11个月,我需要找到那个源代码并尝试你的解决方案。 - Mohamed Ennahdi El Idrissi
2
@MohamedEnnahdiElIdrissi 我刚刚上传了代码:https://github.com/doleron/ajax-row-update-primefaces - Duloren

0
要么使用类似OmniFaces的实用程序库的“ajax”功能,要么在PrimeFaces选择器中进行创意。
在两种情况下,您都需要访问例如“当前”行或rowId。但是由于您在行内拥有按钮,因此这不应该是问题。不幸的是,我没有时间为您创建示例。

我被限制使用PrimeFaces。问题是“选择当前行”以进行更新。 - GregD

0

我尝试使用 uptate = "@parent:componentAnotherColumn",它可以正常工作。只更新同一行。

 <p:column>    
       <p:selectBooleanCheckbox value="#{atributoVar.booleanValue}">
            <p:ajax process="@this" update="@parent:componentAnotherColumn"/>
       </p:selectBooleanCheckbox>
 </p:column>
 <p:column>                            
     <p:selectBooleanCheckbox id="componentAnotherColumn" value="#{!atributoVar.booleanValue}"/>
 </p:column>                    

这不是更新整行,而只是单个兄弟节点。 - Kukeltje

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接