f:ajax和输入ui:repeat - 为什么没有调用getter?

时间:2011-10-28 17:23:50

标签: ajax jsf primefaces

我无法理解为什么当我在ui中重复时,我的吸气剂没有被调用。重复。我正在使用Glassfish 3.1.1 / Mojarra 2.1.3。

下面的代码将呈现类似

的表格
Alice [empty input] [empty output]  [link: update value] [link: cancel]
Bob   [empty input] [empty output]  [link: update value] [link: cancel]

如果我点击Alice行上的“更新值”,然后在“Bob”行上“更新值”,我最终得到:

Alice [Alice] Alice
Bob   [Alice] Bob

我不明白为什么“Bob”行的输出正在拾取“Alice”。这就像在渲染响应阶段没有调用getter,而是来自托管bean的旧值在更新模型值阶段停留在UIInput上。

奇怪的是,如果我在Alice行上点击“更新值”,然后“取消”,然后在Bob行上“更新值”,我得到预期结果。

另外,如果我将“@form”添加到“更新值”链接上的render = ...,我将看到正确的值(尽管它们将在每一行上重复)。我不喜欢这个,主要是因为我不想更新整个表来处理单行。

可能导致这种情况的原因是什么?我对JSF生命周期缺少什么?

此外 - 相同的模式在ui之外工作正常:重复。在这种情况下,h:inputText似乎总是使用来自托管bean的正确值刷新,并按照我的预期在“呈现响应”阶段调用getter。

这最初使用的是PrimeFaces p:commandLink,但是我得到了与标准JSF h完全相同的行为:commandLink和f:ajax。

此外,我知道PrimeFaces行编辑器,这可能是一般整体问题的更好解决方案 - 我仍然想知道为什么这不起作用。

谢谢!

相关的XHTML如下

<h:form id="testForm">
    <table style="width:400px; ">
    <ui:repeat value="#{testBean.customers}" var="customer" varStatus="status">
    <tr>
        <td><h:outputText id="output" value="#{customer.name}"/></td>
        <td><h:inputText id="input" value="#{testBean.customerEdit.name}"/></td>
        <td><h:outputText id="otherOutput" value="#{testBean.customerEdit.name}"/></td>
        <td>
            <h:commandLink actionListener="#{testBean.edit(status.index)}">
                <f:ajax execute="@this" render="input otherOutput"/>
                Update value
            </h:commandLink>
            <h:commandLink actionListener="#{testBean.cancel}">
                <f:ajax execute="@this" render="input otherOutput"/>
                Cancel
            </h:commandLink>
        </td>
    </tr>
    </ui:repeat>
    </table>
</h:form>

“testBean”托管bean是视图范围的:

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

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

@ViewScoped
@ManagedBean
public class TestBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
public static class Customer {
    private String name;

    public Customer(String name) {
        this.name = name;
    }

    public String getName() {
        System.out.println("returning name: " + name);
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

private List<Customer> customers;
private Customer customerEdit = new Customer(null);

@PostConstruct
public void init() {
    customers = Arrays.asList(new Customer("Alice"), 
            new Customer("Bob"), new Customer("Carol"), new Customer("David"), new Customer("Eve"));
}
public Customer getCustomerEdit() {
    return customerEdit;
}
public void setCustomerEdit(Customer customerEdit) {
    this.customerEdit = customerEdit;
}

public void edit(int index) {
    System.out.println("Called edit with index: " + index);
    customerEdit = new Customer(customers.get(index).getName());
}

public void save(int index) {
    System.out.println("Called save with index: " + index + " new name = " + customerEdit.getName());
    customers.set(index, customerEdit);
    customerEdit = null;
}

public void cancel() {
    System.out.println("Called cancel");
    customerEdit = null;
}
public List<Customer> getCustomers() {
    return customers;
}
public void setCustomers(List<Customer> customers) {
    this.customers = customers;
}
}

1 个答案:

答案 0 :(得分:0)

你的问题在于这一行:

 <h:commandLink actionListener="#{testBean.edit(status.index)}">

你不能以这种方式向actionlisteners发送参数,这不是它的工作原理。您需要将该行更改为:

<h:commandLink actionListener="#{testBean.edit}" customerIndex="#{status.index}>

然后将编辑方法更改为类似的内容。

public void edit(ActionEvent ae) {
    int index = ae.getComponent().getAttributes().get("customerIndex");
    System.out.println("Called edit with index: " + index);
    customerEdit = new Customer(customers.get(index).getName());
}

此外,我不确定您的“保存”方法与其他任何内容的关系,但这可能只是因为您跳过了一些不相关的代码。

编辑:你可以通过这种方式发送参数,如果它是一个javascript方法,但不是托管bean或#{}标签内的任何其他内容。