【问题标题】:h:selectManyCheckbox with omnifaces.SelectItemsConverter does not preselect the itemsh:selectManyCheckbox with omnifaces.SelectItemsConverter 不预选项目
【发布时间】:2013-12-02 11:06:58
【问题描述】:

我正在使用JSF 2.0、PrimeFacesOmniFaces

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

Disciplinas 显示为:

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

这很好用。当我选择一些学科并提交表单时,带有所选Disciplines 的新Course 将正确插入数据库中。

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

代码相同:

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

}

这是怎么引起的,我该如何解决?

【问题讨论】:

  • 您能否也显示您的实体类 (Disciplina) 的代码?
  • 好的,等一下,我会更新问题

标签: jsf jsf-2 omnifaces selectmanycheckbox


【解决方案1】:

默认情况下,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() 的设计使您可以轻松地将其保存在所有实体的抽象基类中,这样您就无需在所有实体上复制粘贴相同的内容) em>

  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,这是表示全新且未持久实体的正确方法) em>

    并按如下方式使用

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

【讨论】:

  • 再次感谢 BalusC!我今天早上解决了这个问题。我做了一个快速修复,现在正在工作 - 但正是你正在做的事情,但更难实施。所以,再一次,你是最好的答案:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
相关资源
最近更新 更多