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

≡放荡痞女 提交于 2020-01-05 04:03:31

问题


I'm using JSF 2.0, PrimeFaces and OmniFaces.

I have 2 dialogs with <h:selectManyCheckbox>. The first dialog creates a new Course:

The Disciplinas are presented as:

<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 Disciplines is properly inserted in the DB.

However, when I try to retrieve an existing Course from the DB, the saved Disciplines are not preselected.

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:

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:

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?


回答1:


By default, the SelectItemsConverter relies on toString() of the entity to match the selected items. 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.

You've basically 2 options, also hinted in SelectItemsConverter showcase and javadoc:

  1. Implement a toString method that uniquely identifies the entity and which makes sense as an identifier. 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)

  2. Or, if implementing such a toString() is not an option for some reason (e.g. relying on generated classes which can't be modified afterwards (neither the generator template)), then extend the converter as follows:

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

    And use it as follows

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


来源:https://stackoverflow.com/questions/20062355/hselectmanycheckbox-with-omnifaces-selectitemsconverter-does-not-preselect-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!