Client Side Validation Framework implements JSF validation API within the browser.
<div class="card">
    <h:form>
        <p:messages>
            <p:autoUpdate/>
        </p:messages>
        <h:panelGrid id="grid" columns="4" cellpadding="7">
            <h:outputLabel for="name" value="Name:"/>
            <p:inputText id="name" value="#{validationView.text}" required="true" label="Name"/>
            <p:message for="name"/>
            <h:outputText value="#{validationView.text}"/>
            <p:outputLabel for="number" value="Number:"/>
            <p:inputNumber id="number" value="#{validationView.integer}">
                <f:validateLength minimum="2" maximum="3"/>
            </p:inputNumber>
            <p:message for="number"/>
            <h:outputText value="#{validationView.integer}"/>
            
            <h:outputLabel for="color" value="Color:"/>
            <p:colorPicker id="color" value="#{validationView.color}" required="true" label="Color"/>
            <p:message for="color"/>
            <h:outputText value="#{validationView.color}"/>
            <h:outputLabel for="dd" value="Double:"/>
            <p:inputText id="dd" value="#{validationView.doubleNumber}"
                            converterMessage="Cannot convert to double.">
                <f:validateDoubleRange minimum="5.5" maximum="8.5"/>
            </p:inputText>
            <p:message for="dd"/>
            <h:outputText value="#{validationView.doubleNumber}"/>
            <h:outputLabel for="money" value="Currency ($):"/>
            <p:inputText id="money" value="#{validationView.money}" label="Currency">
                <f:convertNumber type="currency" currencySymbol="$"/>
            </p:inputText>
            <p:message for="money"/>
            <h:outputText value="#{validationView.money}">
                <f:convertNumber type="currency" currencySymbol="$"/>
            </h:outputText>
            <h:outputLabel for="regex" value="Regex (^[a-zA-Z]+$):"/>
            <p:inputText id="regex" value="#{validationView.regexText}"
                            validatorMessage="Value does not match pattern.">
                <f:validateRegex pattern="^[a-zA-Z]+$"/>
            </p:inputText>
            <p:message for="regex"/>
            <h:outputText value="#{validationView.regexText}"/>
            <h:outputLabel for="date" value="Date (java.util.Date)"/>
            <p:inputText id="date" value="#{validationView.date}" label="Date (java.util.Date)">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </p:inputText>
            <p:message for="date"/>
            <h:outputText value="#{validationView.date}">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </h:outputText>
            <h:outputLabel for="date2" value="Date (java.util.Date; PF Calendar)"/>
            <p:calendar id="date2" value="#{validationView.date2}" pattern="MM/dd/yyyy"
                        label="Date (java.util.Date; PF Calendar)">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </p:calendar>
            <p:message for="date2"/>
            <h:outputText value="#{validationView.date2}">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </h:outputText>
            <h:outputLabel for="date3" value="Date (java.util.Date; PF DatePicker)"
                           />
            <p:datePicker id="date3" value="#{validationView.date3}" pattern="MM/dd/yyyy"
                            label="Date (java.util.Date; PF DatePicker)">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </p:datePicker>
            <p:message for="date3"/>
            <h:outputText value="#{validationView.date3}">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </h:outputText>
            <h:outputLabel for="localDate" value="LocalDate (Java8)"/>
            <p:inputText id="localDate" value="#{validationView.localDate}" label="LocalDate (Java8)">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </p:inputText>
            <p:message for="localDate"/>
            <h:outputText value="#{validationView.localDate}">
                <f:convertDateTime pattern="MM/dd/yyyy"/>
            </h:outputText>
            <h:outputLabel for="localDate2" value="LocalDate (Java8; PF Calendar)"
                           />
            <p:calendar id="localDate2" value="#{validationView.localDate2}" pattern="MM/dd/yyyy"
                        label="LocalDate (Java8; PF Calendar)">
                <f:convertDateTime pattern="MM/dd/yyyy" type="localDate"/>
            </p:calendar>
            <p:message for="localDate2"/>
            <h:outputText value="#{validationView.localDate2}">
                <f:convertDateTime pattern="MM/dd/yyyy" type="localDate"/>
            </h:outputText>
            <h:outputLabel for="localDate3" value="LocalDate (Java8; PF DatePicker)"
                           />
            <p:datePicker id="localDate3" value="#{validationView.localDate3}" pattern="MM/dd/yyyy"
                            label="LocalDate (Java8; PF DatePicker)">
                <f:convertDateTime pattern="MM/dd/yyyy" type="localDate"/>
            </p:datePicker>
            <p:message for="localDate3"/>
            <h:outputText value="#{validationView.localDate3}">
                <f:convertDateTime pattern="MM/dd/yyyy" type="localDate"/>
            </h:outputText>
            <h:outputLabel for="desc" value="Description"/>
            <p:inputTextarea id="desc" value="#{validationView.description}" required="true"
                                label="Description">
                <f:validateLength minimum="3" maximum="10"/>
            </p:inputTextarea>
            <p:message for="desc"/>
            <h:outputText value="#{validationView.description}"/>
        </h:panelGrid>
        <p:remoteCommand name="rc" update="grid" process="name number" validateClient="true"/>
        <p:defaultCommand target="btnAjax"/>
        <div class="pt-3">
            <p:commandButton value="Non-Ajax" ajax="false" validateClient="true" styleClass="mr-2" />
            <p:commandButton value="Ajax" id="btnAjax" update="grid"  validateClient="true" styleClass="mr-2" />
            <p:commandButton value="Partial" update="grid" process="name number" validateClient="true" styleClass="mr-2" />
            <p:commandButton value="Disabled (without CSV)" ajax="false"  styleClass="mr-2"/>
            <p:commandButton value="Remote Command" type="button" onclick="rc()" />
        </div>
        
    </h:form>
</div>
package org.primefaces.showcase.view.csv;
import java.time.LocalDate;
import java.util.Date;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
@Named
@RequestScoped
public class ValidationView {
    private String text;
    private String color;
    private String description;
    private Integer integer;
    private Double doubleNumber;
    private Double money;
    private String regexText;
    private Date date;
    private Date date2;
    private Date date3;
    private LocalDate localDate;
    private LocalDate localDate2;
    private LocalDate localDate3;
    private String uiLibrary;
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Integer getInteger() {
        return integer;
    }
    public void setInteger(Integer integer) {
        this.integer = integer;
    }
    public Double getDoubleNumber() {
        return doubleNumber;
    }
    public void setDoubleNumber(Double doubleNumber) {
        this.doubleNumber = doubleNumber;
    }
    public Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }
    public String getRegexText() {
        return regexText;
    }
    public void setRegexText(String regexText) {
        this.regexText = regexText;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    public Date getDate2() {
        return date2;
    }
    public void setDate2(Date date) {
        this.date2 = date;
    }
    public Date getDate3() {
        return date3;
    }
    public void setDate3(Date date) {
        this.date3 = date;
    }
    public LocalDate getLocalDate() {
        return localDate;
    }
    public void setLocalDate(LocalDate localDate) {
        this.localDate = localDate;
    }
    public LocalDate getLocalDate2() {
        return localDate2;
    }
    public void setLocalDate2(LocalDate localDate) {
        this.localDate2 = localDate;
    }
    public LocalDate getLocalDate3() {
        return localDate3;
    }
    public void setLocalDate3(LocalDate localDate) {
        this.localDate3 = localDate;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getUiLibrary() {
        return uiLibrary;
    }
    public void setUiLibrary(String uiLibrary) {
        this.uiLibrary = uiLibrary;
    }
    public void modifyValues() {
        setText("Mike");
        setInteger(123);
    }
    public void modifyInteger() {
        setInteger(456);
    }
    public void clearValues() {
        setText(null);
        setInteger(null);
        setDoubleNumber(null);
    }
}