My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

luni, 29 februarie 2016

Validating multiple fields by a custom validator method or by a managed bean instance which implements the MultiFieldValidator interface

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.

<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:


Is time for ValidateMultiple to enter in the scene! As we said earlier, we will implement the MultiFieldValidator interface and override the validateValues() method. This method receives a list of UIInputs representing the input components that enters in validation and a list of Objects representing the local values of these components (these are the values that should be validated). Now, we need to provide the code specific to our validation constraint. We can accomplish this in multiple ways, but notice that our list of components contains two instances: one instance of org.primefaces.component.picklist.PickList and one instance of org.primefaces.component.selectmanycheckbox.SelectManyCheckbox; moreover, the list of values should contain an instance of org.primefaces.model.DualListModel and an instance of List):

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


But, if in the PickList, we also select the Pablo Cuevas and Jeremy Chardy players then the submission will become valid:


The complete application is named ValidateMultiple.

Read more such goodies in:

PrimeFaces & OmniFaces - Powers Combined

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors