The OmniFaces <o:validateMultiple/> allows
the developer to validate multiple fields by either a custom validator method
or, by a managed bean instance which implements the MultiFieldValidator
interface. In the first approach, the method that performs the validation must
respect the following signature:
public class FooBean {
// ...
public boolean fooMethod(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
// ...
}
And, it is referenced from <o:validateMultiple/> like below:
<o:validateMultiple ... validator="#{fooBean.fooMethod}" />
In the second approach, we implement the MultiFieldValidator interface and override the validateValues() method:
@Override
public class FooBean implements MultiFieldValidator {
// ...
public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
// ...
}
And, it is referenced from <o:validateMultiple/> like below:
<o:validateMultiple ... validator="#{fooBean}" />
Let's have an examples that uses the second approach. For this let's suppose that we have a PrimeFaces PickList and a SelectManyCheckbox. Both components will be populated with the same data and our validation constraint imposes that the selected data from the PickList should contain the data checked in the SelectManyCheckbox. Before we add the validation constrains, let's have some preparations. So, let's say that the used data are instances of the Player class listed below:
public class Player implements Serializable {
private static final long serialVersionUID = 1L;
private int rank;
private String name;
public Player(int rank, String name) {
this.rank = rank;
this.name = name;
}
// getters and setters
// This method is needed for using the OmniFaces ListConverter
// and SelectItemsConverter. Both need that our entity has a
// good toString() implementation
@Override
public String toString() {
return "Player{" + "rank=" + rank + ", name=" + name + '}';
}
}
Furthermore, let's create a few Players and let's prepare the data accordingly to PickList and SelectManyCheckbox requirements:
@Named
@ViewScoped
public class PlayerBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Player> players;
private List<Player> selectedviaCheckbox;
private DualListModel<Player> model;
@PostConstruct
public void init() {
selectedviaCheckbox = new ArrayList<>();
players = asList(
new Player(8, "Tomas Berdych"),
new Player(20, "Jurgen Melzer"),
...
);
model = new DualListModel<>(
new ArrayList<>(players),
new ArrayList<Player>()
);
}
// getters and setters
// some dummy action
public void playersAction(){
Messages.addGlobalInfo("The selected players are valid");
}
}
Next, we can expose this data to the user (notice that we have used the omnifaces.ListConverter for PickList and omnifaces.SelectItemsConverter for SelectManyCheckbox.
public class FooBean {
// ...
public boolean fooMethod(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
// ...
}
And, it is referenced from <o:validateMultiple/> like below:
<o:validateMultiple ... validator="#{fooBean.fooMethod}" />
In the second approach, we implement the MultiFieldValidator interface and override the validateValues() method:
@Override
public class FooBean implements MultiFieldValidator {
// ...
public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
// ...
}
// ...
}
And, it is referenced from <o:validateMultiple/> like below:
<o:validateMultiple ... validator="#{fooBean}" />
Let's have an examples that uses the second approach. For this let's suppose that we have a PrimeFaces PickList and a SelectManyCheckbox. Both components will be populated with the same data and our validation constraint imposes that the selected data from the PickList should contain the data checked in the SelectManyCheckbox. Before we add the validation constrains, let's have some preparations. So, let's say that the used data are instances of the Player class listed below:
public class Player implements Serializable {
private static final long serialVersionUID = 1L;
private int rank;
private String name;
public Player(int rank, String name) {
this.rank = rank;
this.name = name;
}
// getters and setters
// This method is needed for using the OmniFaces ListConverter
// and SelectItemsConverter. Both need that our entity has a
// good toString() implementation
@Override
public String toString() {
return "Player{" + "rank=" + rank + ", name=" + name + '}';
}
}
Furthermore, let's create a few Players and let's prepare the data accordingly to PickList and SelectManyCheckbox requirements:
@Named
@ViewScoped
public class PlayerBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Player> players;
private List<Player> selectedviaCheckbox;
private DualListModel<Player> model;
@PostConstruct
public void init() {
selectedviaCheckbox = new ArrayList<>();
players = asList(
new Player(8, "Tomas Berdych"),
new Player(20, "Jurgen Melzer"),
...
);
model = new DualListModel<>(
new ArrayList<>(players),
new ArrayList<Player>()
);
}
// getters and setters
// some dummy action
public void playersAction(){
Messages.addGlobalInfo("The selected players are valid");
}
}
Next, we can expose this data to the user (notice that we have used the omnifaces.ListConverter for PickList and omnifaces.SelectItemsConverter for SelectManyCheckbox.
<h:form>
<p:messages id="msgs"/><p:pickList id="playersList" value="#{playerBean.model}" var="t"
itemLabel="#{t.rank}.#{t.name}" itemValue="#{t}">
<o:converter converterId="omnifaces.ListConverter" list="#{playerBean.players}" />
</p:pickList>
<p:selectManyCheckbox id="playersCheckbox" value="#{playerBean.selectedviaCheckbox}"
converter="omnifaces.SelectItemsConverter"
layout="responsive" style="width: 435px; margin-top: 5px;" columns="3">
<f:selectItems value="#{playerBean.players}" var="t"
itemLabel="#{t.rank}.#{t.name}" itemValue="#{t}" />
</p:selectManyCheckbox>
<p:commandButton value="Submit" action="#{playerBean.playersAction()}"
update="msgs" style="margin-top:5px" />
</h:form>
At this moment any combination of selections will be valid, as you can see in figure below:
@Named
@ApplicationScoped
public class ValidatePlayers implements MultiFieldValidator {
@Override
public boolean validateValues(FacesContext fc, List<UIInput> components, List<Object> values) {
List<Player> fromModel;
if (values.get(0) instanceof DualListModel) {
fromModel = ((DualListModel) values.get(0)).getTarget();
return fromModel.containsAll((List) values.get(1));
} else {
fromModel = ((DualListModel) values.get(1)).getTarget();
return fromModel.containsAll((List) values.get(0));
}
}
}
Finally, we need to use <o:validateMultiple/> in page. This is pretty straightforward:
<h:form>
...
<o:validateMultiple id="validateMultiple"
components="playersList playersCheckbox"
validator="#{validatePlayers}"
message="The selected players via checkboxes must be contained by the selected player list." />
</h:form>
This time the selection from above picture is not valid. Checkout the figure below:
The complete application is named ValidateMultiple.
Read more such goodies in:
Read more such goodies in:
Niciun comentariu :
Trimiteți un comentariu