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: