【问题标题】:<p:selectOneMenu listener method returns null when a value is selected<p:selectOneMenu 侦听器方法在选择值时返回 null
【发布时间】:2013-02-05 21:44:23
【问题描述】:

我正在使用 JSF 2.0 和 Primefaces 3.4.2

我在 JSF 页面中有以下内容

<p:selectOneMenu value="#{mb.employee}">
    <f:selectItems value="#{mb.employeeList}" var="emp"
    itemLabel="#{emp.employeeName}" itemValue="#{emp.employeeCode}"/>
    <p:ajax listener="#{mb.changeMethod}" />
</p:selectOneMenu>

问题是当我在 selectOneMenu 中选择一个值时,我在 ManagedBean 的 changeMethod 中得到 null,对于这个 System.out.println("val "+employee.getEmployeeName());

这可能是什么原因?我该如何解决这个问题? 任何 hep 都是非常明显的。

ManagedBean代码

@Named("mb")
@ViewAccessScoped
public class MyBean implements Serializable {

private Employee employee;
private List<Employee> employeeList;

@Inject
EmployeeService employeeService;

@PostConstruct
public void loadEmployees() {
employeeList = employeeService.getEmployees();
}


public void changeMethod() {
System.out.println("val  "+employee.getEmployeeName());
}


/* getters and setters for employee and employeeList */
.... methods
/* */

【问题讨论】:

    标签: java jsf jsf-2 primefaces


    【解决方案1】:

    您没有在 &lt;p:ajax&gt; 组件上指定要处理的表单元素,因此 ajax 请求可能会提交多个值,这些值可能与其他字段验证发生冲突。请记住,如果一个值被提交并且它没有通过验证,那么没有一个请求值被设置到模型中。当您到达 Application(Event) 阶段时,模型值将不会反映任何提交的请求值。

    试试这个:

    <p:selectOneMenu value="#{mb.employee}">
        <f:selectItems value="#{mb.employeeList}" var="emp"
        itemLabel="#{emp.employeeName}" itemValue="#{emp.employeeCode}"/>
        <p:ajax process="@this" partialSubmit="true" listener="#{mb.changeMethod}" />
    </p:selectOneMenu>
    

    您将只提交当前组件请求值以应用于模型。

    编辑:

    实际上这可能不是验证问题,因为没有在 ajax 事件上提交请求值。

    根据 Primefaces 手册:

    处理空字符串组件以处理部分请求。

    更新空字符串组件以使用 ajax 进行更新。

    第二列是默认值。在标准&lt;f:ajax&gt; 中,execute 属性默认为@this,但&lt;p:ajax&gt; 并非如此。如果要提交当前组件,则必须在 process 属性中指定。

    【讨论】:

    • 我已经添加了&lt;p:ajax process="@this" partialSubmit="true",然后是changeMethod is not getting invoked. When I tried only with process="@this". then I am getting null 指针异常`。
    • @Polppan 您的属性设置器或获取器方法中必须有一个空指针。这也可能发生在您的selectOneMenu 组件的converter 中。您正在转换 employee 对象不是吗?
    • 这是因为我没有转换器类吗?是的employeeList 和employee 基本上是Employee 类。
    • @Polppan 是的,您需要为直接绑定到 selectOneMenu 的对象实现转换器。
    • 我将添加一个转换器类并会回复您。
    【解决方案2】:

    您需要将转换器添加到 p:selectOneMenu 以让它知道您正在处理 employee 对象。创建转换器类并将其与 converter 属性一起使用。这是示例转换器。

    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    import javax.faces.convert.Converter;
    import javax.faces.convert.FacesConverter;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Configurable;
    
    @FacesConverter("employeeConverter")
    @Configurable
    public class EmployeeConverter implements Converter {
    
        @Autowired
        EmployeeService employeeService;
    
        public Object getAsObject(FacesContext context, UIComponent component,
                String value) {
            if (value == null || value.length() == 0) {
                return null;
            }
            Long id = Long.parseLong(value);
            return employeeService.findUser(id);
        }
    
        public String getAsString(FacesContext context, UIComponent component,
                Object value) {
            return value instanceof Employee ? ((Employee) value).getId().toString() : "";
        }
    }
    

    【讨论】:

    • Chris 为什么getAsObject 方法没有被调用?只调用getAsString方法?
    • getAsObject 在数据保存时被调用。此时,selectOneMenu 必须返回需要保存的对象。 getAsString 被调用以进行 UI 转换,只是为了查看名称或代码或类似的东西。
    • Chris 在保存之前有什么方法可以测试 `getAsObject' 是否返回正确的值?
    • 我认为只有在需要检索对象进行保存时才会调用 getAsObject。我不确定它会在任何其他阶段被调用。也许这是 javax.faces.convert.Converter 的默认行为。
    • getAsObject 方法也会在部分更新发生时被调用,例如 &lt;p:ajax update。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 2016-07-04
    • 1970-01-01
    • 2017-11-01
    • 2015-10-29
    相关资源
    最近更新 更多