h:selectManyCheckbox with omnifaces.SelectItemsConverter不预先选择项目

时间:2013-11-19 03:05:45

标签: jsf jsf-2 omnifaces selectmanycheckbox

我正在使用JSF 2.0,PrimeFacesOmniFaces

我有<h:selectManyCheckbox>的2个对话框。第一个对话框创建一个新的Course

enter image description here

Disciplina表示为:

<h:selectManyCheckbox id="disciplinas" 
    value="#{cursoMBean.listaDisciplinasDoCurso}"
    converter="omnifaces.SelectItemsConverter">
    <f:selectItems value="#{cursoMBean.listaTodasDisciplinas}"
        var="disciplina" itemValue="#{disciplina}"
        itemLabel="#{disciplina.nome}" />
</h:selectManyCheckbox>

这很好用。当我选择一些规则并提交表单时,带有所选Course的新Discipline已正确插入数据库。

但是,当我尝试从数据库中检索现有Course时,未预先选择已保存的Discipline

enter image description here

代码相同:

<h:selectManyCheckbox id="disciplinas" 
    value="#{cursoMBean.listaDisciplinasDoCurso}"
    converter="omnifaces.SelectItemsConverter">
    <f:selectItems value="#{cursoMBean.listaTodasDisciplinas}"
        var="disciplina" itemValue="#{disciplina}"
        itemLabel="#{disciplina.nome}" />
</h:selectManyCheckbox>

这是支持bean:

private ArrayList<Disciplina> listaTodasDisciplinas;
private ArrayList<Disciplina> listaDisciplinasDoCurso;

public CursoMBean() {
    if (listaTodasDisciplinas == null) {
        listaTodasDisciplinas = controleDisciplina.consulta();
    }

    if (listaDisciplinasDoCurso == null) {
        listaDisciplinasDoCurso = new ArrayList<Disciplina>();
    }
}

// When user selects one Course to edit, this method is called:
public void setSelecionado(Curso selecionado) {
    this.selecionado = selecionado;

    if (selecionado != null) {
        listaTodasDisciplinas = controleDisciplina.consulta();
        listaDisciplinasDoCurso = controleCurso.listaDisciplinasAssociadas(selecionado);
    }
}

这是Disciplina实体:

public class Disciplina {

    private int id;
    private String nome;

    public Disciplina() {
    }

    public Disciplina(int id, String nome) {
        this.id = id;
        this.nome = nome;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        if (!(nome.isEmpty() || nome == " " || nome == "  ")){
            this.nome = nome;
        }
    }

}

这是如何引起的?如何解决?

1 个答案:

答案 0 :(得分:2)

默认情况下,SelectItemsConverter依赖于实体的toString()来匹配所选项目。但是,您的实体没有实现toString(),因此依赖于默认fqn@hashcode结果,即使它们具有相同的值,当创建两个物理上不同的Disciplina实例时,结果也不相同

您基本上有2个选项,也在SelectItemsConverter showcasejavadoc中暗示:

  1. 实现唯一标识实体的toString方法,并将其作为标识符。例如,

    @Override
    public String toString() {
        return String.format("%s[id=%d]", getClass().getSimpleName(), getId());
    }
    

    (请注意,此toString()的设计使您可以轻松地将其保存在所有实体的抽象基类中,这样您就不需要在所有实体上对其进行复制。

  2. 或者,如果由于某种原因实现这样的toString()不是一个选项(例如依赖于之后无法修改的生成类(既不是生成器模板)),那么将转换器扩展为如下:

    @FacesConverter("disciplinaSelectItemsConverter")
    public class DisciplinaSelectItemsConverter extends SelectItemsConverter {
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            Integer id = (value instanceof Disciplina) ? ((Disciplina) value).getId() : null;
            return (id != null) ? String.valueOf(id) : null;
        }
    
    }
    

    (注意:您应该使用Integer代替int作为ID,int不能是null,这是表示身份的正确方法全新且无人值守的实体)

    并按如下方式使用

    <h:selectManyCheckbox ... converter="disciplinaSelectItemsConverter">