简体   繁体   English

h:selectManyCheckbox和omnifaces.SelectItemsConverter不会预选项目

[英]h:selectManyCheckbox with omnifaces.SelectItemsConverter does not preselect the items

I'm using JSF 2.0, PrimeFaces and OmniFaces . 我正在使用JSF 2.0, PrimeFacesOmniFaces

I have 2 dialogs with <h:selectManyCheckbox> . 我有两个<h:selectManyCheckbox>对话框。 The first dialog creates a new Course : 第一个对话框创建一个新Course

在此处输入图片说明

The Disciplina s are presented as: 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>

This works fine. 这很好。 When I select some disciplines and submit the form, then the new Course with the selected Discipline s is properly inserted in the DB. 当我选择一些学科并提交表格后,带有所选Discipline的新Course将正确插入数据库中。

However, when I try to retrieve an existing Course from the DB, the saved Discipline s are not preselected. 但是,当我尝试从数据库中检索现有Course ,未预先选择保存的Discipline

在此处输入图片说明

The code is the same: 代码是一样的:

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

Here's the backing bean: 这是支持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);
    }
}

Here's the Disciplina entity: 这是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;
        }
    }

}

How is this caused and how can I solve it? 这是怎么引起的,我该如何解决?

By default, the SelectItemsConverter relies on toString() of the entity to match the selected items. 默认情况下, SelectItemsConverter依赖于实体的toString()来匹配所选项目。 Your entity however doesn't have a toString() implemented and is thus relying on default fqn@hashcode result which is not the same when two physically different Disciplina instances are created even though they have the same value. 但是,您的实体没有实现toString() ,因此依赖于默认的fqn@hashcode结果,当创建两个物理上不同的Disciplina实例时,即使它们具有相同的值,该结果也不相同。

You've basically 2 options, also hinted in SelectItemsConverter showcase and javadoc : 您基本上有2个选择,在SelectItemsConverter 展示柜javadoc中也有提示:

  1. Implement a toString method that uniquely identifies the entity and which makes sense as an identifier. 实现一个toString方法,该方法唯一地标识实体,并作为标识符有意义。 For example, 例如,

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

    (note that this toString() is designed such that you can easily keep it in an abstract base class of all your entities, so that you don't need to copypaste the same over all your entities) (请注意,此toString()的设计使您可以轻松地将其保留在所有实体的抽象基类中,从而无需在所有实体上都复制粘贴相同的东西)

  2. Or, if implementing such a toString() is not an option for some reason (eg relying on generated classes which can't be modified afterwards (neither the generator template)), then extend the converter as follows: 或者,如果出于某种原因(例如,依赖于生成的类,以后不能对其进行修改(既不是生成器模板),则不希望实现此类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; } } 

    (note: you should really be using Integer instead of int as ID, the int cannot be null which is the correct way to represent a brand new and unpersisted entity) (注意:您实际上应该使用Integer而不是int作为ID, int不能为null ,这是表示全新的持久实体的正确方法)

    And use it as follows 并如下使用

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM