【问题标题】:FacesException: DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabledFacesException:启用选择时,DataModel 必须实现 org.primefaces.model.SelectableDataModel
【发布时间】:2012-05-18 14:29:39
【问题描述】:

我正在尝试学习 PF,所以我首先显示数据表并导航到 rowClick 传递参数的下一页,但遇到以下错误。我为那个问题发现了类似的问题,但还没有运气。我希望有人能帮助我。

我收到以下错误:

DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.

Caused by:
javax.faces.FacesException - DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.

我的主页:

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

<h:head>
<title>Primefaces 3.1</title>

</h:head>
<h:body>
    <h:form id="form">          
            <p:dataTable value="#{tableBean.cars}" var="var" rowkey="#{var.model}" 
            selection="#{tableBean.car}" selectionMode="single">
            <p:column>  <f:facet name="header">
                                <h:outputText styleClass="outputText" value="Model"></h:outputText>
                            </f:facet>
                            <h:outputText styleClass="outputText"
                                value="#{var.model}"></h:outputText>
                        </p:column>
                        <p:column>
                            <f:facet name="header">
                                <h:outputText styleClass="outputText" value="Color"></h:outputText>
                            </f:facet>
                            <h:outputText styleClass="outputText"
                                value="#{var.randomColor}"></h:outputText>
                        </p:column></p:dataTable>                               
        </h:form>
</h:body>
</html>

我的 bean 类:

@ManagedBean
@ViewScoped
public class TableBean extends ListDataModel<Car> implements SelectableDataModel<Car>{

    private List<Car> cars;
    private Car car;

    public List<Car> getCars() {

        cars = new ArrayList<Car>();
        Car car1 = new Car();
        car1.setModel("BMW");
        car1.setRandomColor("Black");
        cars.add(car1);
        Car car2 = new Car();       
        car2.setModel("Audi");
        car2.setRandomColor("White");
        cars.add(car2);

        return cars;
    }

    public String onRowSelect(){
        System.out.println("Row Click!!!");
        return "otherpage";//Does this nav works???if not how???
    }

    public Car getCar() {
        return car;
    }

    @Override
    public Car getRowData(String pArg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object getRowKey(Car pArg0) {
        // TODO Auto-generated method stub
        return null;
    }   
    }

其他豆类:

public class Car{

    private String model;   
    private String randomColor; 

    public String getRandomColor() {
        return randomColor;
    }
    public void setRandomColor(String pRandomColor) {
        randomColor = pRandomColor;
    }

    public String getModel() {
        return model;
    }
    public void setModel(String pModel) {
        model = pModel;
    }

}

【问题讨论】:

    标签: jsf-2 primefaces


    【解决方案1】:

    如果您没有在&lt;p:dataTable&gt; 上指定rowKey 属性,则#{tableBean.cars} 必须实现SelectableDataModel

    但是,您已经在 #{tableBean} 上实现了它。这个不对。您可以在PrimeFaces showcase 中找到正确的示例。基本上,根据展示代码示例,您的 TableBean 类必须如下所示:

    @ManagedBean
    @ViewScoped
    public class TableBean implements Serializable {
    
        private List<Car> cars;
        private Car car;
        private CarDataModel carsModel;
    
        public TableBean() {
            cars = new ArrayList<Car>();
            // Populate cars here and thus NOT in the getter method!
            carsModel = new CarDataModel(cars);
        }
    
        // ...
    }
    

    CarDataModel 看起来像这样(同样,只是从 PrimeFaces 展示代码示例复制而来):

    public class CarDataModel extends ListDataModel<Car> implements SelectableDataModel<Car> {  
    
        public CarDataModel() {
        }
    
        public CarDataModel(List<Car> data) {
            super(data);
        }
    
        @Override
        public Car getRowData(String rowKey) {
            List<Car> cars = (List<Car>) getWrappedData();
    
            for(Car car : cars) {
                if(car.getModel().equals(rowKey))
                    return car;
            }
    
            return null;
        }
    
        @Override
        public Object getRowKey(Car car) {
            return car.getModel();
        }
    
    }
    

    最后使用#{tableBean.carsModel} 代替#{tableBean.cars} 作为&lt;p:dataTable&gt; 的值。与展示示例中的完全相同。

    <p:dataTable value="#{tableBean.carsModel}" var="car" ... />
    

    另一种更简单的方法是在&lt;p:dataTable&gt; 上指定rowKey 属性。

    <p:dataTable value="#{tableBean.cars}" var="car" rowKey="#{car.model}" ... />
    

    这样你就不需要整个SelectableDataModel。您只需要确保它永远不是 null 并且在各行中始终是唯一的。另见DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled, but I have already defined rowKey

    【讨论】:

    • 感谢BalusC的评论,我有几个问题,rowKey有什么用?是为了显示表格列的唯一值吗?如果我在同一个表中说 2 个主键怎么办。另一个问题是,如果我使用 rowKey,我不必实现 CarDataModel,你的意思是什么,你能稍微解释一下吗……你还能解释一下 中的选择属性的作用。
    • rowKey 基本上告诉 PrimeFaces 行的唯一标识符是什么。 selection 基本上告诉 PrimeFaces 它必须在哪里获取/设置选定行的引用。 SelectableDataModel 的重点是能够根据行对象本身已经可用的条件之外的其他条件识别唯一行(您需要rowKey)。
    • 如果有2个主键怎么办,这种情况下怎么办?
    • 要么使用复合键,要么创建SelectableDataModel
    • 请注意,即使您可能已经定义了 rowKey 属性 如果 所述属性返回 null(例如,它未初始化),您仍然可能会遇到相同的错误。
    【解决方案2】:

    确保在填充数据表的“value=..”的 bean 方法中设置 rowKey 参数。我的返回此错误,因为 rowKey 为空。

    【讨论】:

      【解决方案3】:

      您不必在 managedbean 中实现数据模式,只需在数据表的属性中指定“rowkey”,如下所示:rowkey="{mbean.atribute1}"
      -- atribute1 必须显示在数据表列中。

      必须

      【讨论】:

      • 行键参数不需要在数据表中显示为列。
      【解决方案4】:

      它适用于我的项目,它使用组合键作为行键,例如:rowKey="#{course.getCompositeKey()

      由于我没有compositeKey 变量,我只是在我的课程类(在您的情况下是汽车类)中创建了一个变量。 2 个主键是字符串,所以我只是说 this.compositeKey=this.courseNumber+this.product--您只需使用 Car 类中的任何 2 个主键,而不是 courseNumber 和 product。

      【讨论】:

        猜你喜欢
        • 2012-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        • 1970-01-01
        • 2014-12-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多