Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

jsf 2 - FacesException: DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled

I am trying to learn PF so I started with displaying datatable first and navigating to next page on rowClick passing parameters, but got stuck with the following error. I found similar problem for that question but no luck yet. I hope somebody will help me out.

I am getting following error:

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.

my Page:

 <?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>

my bean Classes:

@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;
    }   
    }

OtherBean:

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;
    }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The #{tableBean.cars} must implement SelectableDataModel if you don't specify the rowKey attribute on the <p:dataTable>.

You have however implemented it on the #{tableBean} instead. This is not right. You can find correct examples in the PrimeFaces showcase. Basically, your TableBean class must look like this according to the showcase code example:

@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);
    }

    // ...
}

Where the CarDataModel look like this (again, just copied from PrimeFaces showcase code example):

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();
    }

}

Finally use #{tableBean.carsModel} instead of #{tableBean.cars} as value of <p:dataTable>. Exactly as in the showcase example.

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

Another, easier, way is to just specify the rowKey attribute on the <p:dataTable>.

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

This way you don't need the whole SelectableDataModel. You only need to ensure that it's never null and always unique across the rows. See also DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled, but I have already defined rowKey.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...