3

When using a component we specify how to validate it with a required, maxlength or a validator and those validation are enforced on the server which is great.

When using Primefaces inputMask we can specify a mask. The mask lead us to think that the user input will always match this mask. Unfortunately this is not the case and we have to code a validator to make sure that the user input will be the way we want it to be. So, unless I am missing something, the "client-side only" behavior of the inputMask is just good enough to provide a hint to the user on how to fill a field.

Is there a generic validator than can be paired with p:inputMask to make sure that the user input is really matching the mask?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
ForguesR
  • 3,558
  • 1
  • 17
  • 39

1 Answers1

6

PrimeFaces doesn't offer that out the box.

It should however be relatively trivial to convert a mask pattern to a regex pattern using a simple for loop over a character array. You can then use this regex pattern to validate the value.

E.g.

<p:inputMask ... validator="maskValidator">

with

@FacesValidator("maskValidator")
public class MaskValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String submittedValue = context.getExternalContext().getRequestParameterMap().get(component.getClientId(context));

        if (submittedValue == null || submittedValue.isEmpty()) {
            return; // Let @NotNull / required="true" handle.
        }

        InputMask input = (InputMask) component;
        String mask = input.getMask();
        StringBuilder regex = new StringBuilder();

        for (char c : mask.toCharArray()) {
            switch (c) {
                case 'a': regex.append("[a-zA-Z]"); break;
                case '9': regex.append("[0-9]"); break;
                case '?': case '+': case '*': regex.append(c); break;
                default: regex.append(Pattern.quote(Character.toString(c))); break;
            }
        }

        if (!submittedValue.matches(regex.toString())) {
            throw new ValidatorException(new FacesMessage(submittedValue + " does not match " + mask));
        }
    }
}

Note that the validator works with unconverted submitted value, not with the passed-in 3rd argument, which might be (implicitly) converted beforehand and thus have a potentially different toString() representation.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555