4

I have one doubt about create selectBooleanCheckbox using ui:repeat.

I have one class called Filter whith theses fields.

class Filter {

    private Boolean comissaoAdesao;
    private Boolean comissaoSaque;
    private Boolean comissaoSaqueAdicional;
    private Boolean comissaoCompra;
    private Boolean cidadeUF;
    private Boolean publicidade;

    // getter e setter
}

So I want to know if is possible to link the fields to selectBooleanCheckbox using ui:repeat.

My method is:

if (NullUtil.isNull(this.colunasAnalitico)) {
    Map<String, Boolean> map = new TreeMap<String, Boolean>() {
        {
            put("Comissão adesão", filter.getComissaoAdesao());
            put("Comissão saque", filter.getComissaoSaque());
            put("Comissão saque adicional", filter.getComissaoSaqueAdicional());
            put("Comissão compra", filter.getComissaoCompra());
            put("Cidade/UF", filter.getCidadeUF());
            put("Publicidade", filter.getPublicidade());
        }
    };
    this.colunasAnalitico = new ArrayList<Entry<String, Boolean>>(map.entrySet());
}
return colunasAnalitico;

And my page code is:

<ui:repeat >
    <p:row>
        <c:set var="campo" value="bean.filter.#{colunaAnalitico.value}"/>
        <p:column style="width: 2%">
            <p:selectBooleanCheckbox label="#{colunaAnalitico.key}" value="#{campo}"/>
        </p:column>
        <p:column>
            <p:outputLabel value="#{campo}"/>
        </p:column>                         
    </p:row>
</ui:repeat>
user3503888
  • 435
  • 5
  • 17

3 Answers3

4

Simply put: the view must match the model.

In your current model, you've a bunch of fixed boolean properties, not a dynamically sized array or collection of boolean properties. The <ui:repeat> can only iterate over a dynamically sized array or collection. In your model, you already know all possible boolean properties beforehand. So, you can just define them all in the view. Technically, you don't need an <ui:repeat> at all. Your initial attempt with value="#{someBoolean}" instead of value="#{bean.someBoolean}" failed for same technical reason as explained here.

Given an example entity of

public class Filter {

    private Boolean option1;
    private Boolean option2;
    private Boolean option3;

    // ...
}

You can just do so:

<p:panelGrid columns="2">
    <p:selectBooleanCheckbox id="option1" value="#{bean.filter.option1}" />
    <p:outputLabel for="option1" value="Filter option one" />

    <p:selectBooleanCheckbox id="option2" value="#{bean.filter.option2}" />
    <p:outputLabel for="option2" value="Filter option two" />

    <p:selectBooleanCheckbox id="option3" value="#{bean.filter.option3}" />
    <p:outputLabel for="option3" value="Filter option three" />
</p:panelGrid>

In case you was concerned about non-DRY code, simply put this all in a reusable include file or perhaps even tagfile or composite taking #{bean.filter} as value.

<my:selectFilterOptions value="#{bean.filter}" />

In case you was concerned about the label values for some reason, you need to realize that they don't belong in the model at all. They belong in the view, or at least in a resource bundle properties file.

filter_option.option1 = Filter option one
filter_option.option2 = Filter option two
filter_option.option3 = Filter option three
<p:outputLabel for="option1" value="#{i18n['filter_option.option1']}" />
...
<p:outputLabel for="option2" value="#{i18n['filter_option.option2']}" />
...
<p:outputLabel for="option3" value="#{i18n['filter_option.option3']}" />

See also:


From the other side on, it's also very good possible that the model is simply poorly designed. The most straightforward refactoring approach of a bunch of fixed booleans would be an enum.

public enum FilterOption {

    OPTION1,
    OPTION2,
    OPTION3;

}

You can simply hold them in an array or a collection (an array is easier so you don't need a JSF converter; in case you'd like to use JPA @ElementCollection on an @Enumerated and thus can't use an array, consider OmniFaces GenericEnumConverter).

public class Filter {

    private FilterOption[] options;

    // ...
}

You can supply all available values in the application scope.

@Named
@ApplicationScoped
public class Data {

    public FilterOption[] getFilterOptions() {
        return FilterOption.values();
    }

}

You can localize labels in a resource bundle properties file using enum names as keys.

filter_option.OPTION1 = Filter option one
filter_option.OPTION2 = Filter option two
filter_option.OPTION3 = Filter option three

So you can ultimately use a <p:selectManyCheckbox> instead of <p:panelGrid><p:selectBooleanCheckbox>.

<p:selectManyCheckbox value="#{bean.filter.options}">
    <f:selectItems value="#{data.filterOptions}" var="option"
        itemValue="#{option}" itemLabel="#{i18n['filter_option.' += option]}" />
</p:selectManyCheckbox>

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Very good, but I have one doubt, if I want to use the boolean values to render or not a column. Wich option will be better? – Diego Macario Nov 16 '15 at 23:51
  • 1
    Not sure what the concrete problem is. – BalusC Nov 17 '15 at 07:53
  • I asked if I used these boolean values to render or columns in one panelgrid, your solution will be the best? – Diego Macario Nov 17 '15 at 11:30
  • 1
    Still not sure what the concrete problem is. As answered, the best solution is that the view matches the model. You can check anything in `rendered` attribute as long as the EL expression evaluates to a `boolean`. See also http://stackoverflow.com/a/4870557 – BalusC Nov 17 '15 at 11:42
1

What you need for your use case is a SelectManyCheckbox

Looking at your code, you can use it somewhat like this:

<p:selectManyCheckbox id="basic" value="#{yourBean.selectedCheckboxes}">
    <f:selectItems value="#{yourBean.colunaAnalitico}" var="item" itemLabel="#{item.key}" itemValue="#{item.value}" />
</p:selectManyCheckbox>

You can even throw in a <ui:param name="campo" value="(what you want to do with item.value that I can't understand from your code)" /> if you need it...

Mikel
  • 1,581
  • 17
  • 35
  • I changed my answer because I have a `Filter` class, that a I link each `label` with that `field` in `Filter class`. – user3503888 Nov 13 '15 at 16:37
1

Your code is a bit strange, check if this meets your requirements:

<ui:repeat value="#{bean.map.entrySet().toArray()}" var="entry" >
    <p:row>
        <p:column style="width: 2%">
            <p:selectBooleanCheckbox label="#{entry.key}" value="#{bean.map[entry.key]}"/>
        </p:column>
        <p:column>
            <p:outputLabel value="#{entry.key}"/>
        </p:column>                         
    </p:row>
</ui:repeat>

bean is your backing bean and map may be TreeMap<String, Boolean>. This worked for me so should also for you.

Related

Community
  • 1
  • 1
Geinmachi
  • 1,251
  • 1
  • 8
  • 20