Wednesday, 5 November 2014

Validation Reusable Text Field

On the Bootstrap4XPages website I came across this validation method for reusable Bootstrap Text Fields by Mark Leussink.
In my opinion this is probably the best validation method that can be used for this type of fields.
In order to document this for myself I describe in this blog post the additions that have to be made to the design of a reusable Bootstrap Text Field as described in this blog post.

Bootstrap includes validation styles for error, warning, and success states on form controls.
To use, add .has-warning, .has-error, or .has-success to the parent element.
Any .control-label, .form-control, and .help-block within that element will receive the validation styles.
On an XPage every input control has an isValid() method.
Therefore is relatively easy to combine these two.

Steps for adding Validation to a reusable Bootstrap Text Field

1. Required Custom Control Property
First a required property has to be added to the reusable Bootstrap Text Field. This property is needed to indicate that the field is required.
required="${compositeData.required}


2. StyleClass Attribute
Secondly the bootstrap validation style 'has-error' has to be added to the styleClass attribute of the form-group and this attribute has to be made div computed.
<xp:div>
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + ( getComponent("inputText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>


3. Validation message
Further an error message has to be added which is to be displayed if the validation is performed and the field is 'not valid'.
<xp:this.validators>
       <xp:validateRequired message="#{javascript:compositeData.fieldLabel + ' is required'}"></xp:validateRequired>
</xp:this.validators>


4. Displaying the HelpText
If the reusable Bootstrap Text Field is using a Help Text it must be ensured that the Help Text is only rendered / displayed if the field is not marked as an error. 
<xp:text escape="true" id="computedField1" styleClass="help-block" value="${compositeData.helpText}">
        <xp:this.rendered><![CDATA[#{javascript:getComponent("inputText1").isValid() && compositeData.helpText != null}]]></xp:this.rendered>
</xp:text>


5. Error Message
The final step is to create a control for showing the error message below the field.
<xp:message id="message1" for="inputText1" styleClass="help-block"></xp:message>

Sample Code Custom Control
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:div>
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + ( getComponent("inputText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>
<xp:div styleClass="form-group">
<xp:label styleClass="col-sm-2 control-label" for="inputText1"
value="${compositeData.fieldLabel}" />
<div class="col-sm-10">
<div class="input-group">
<span class="input-group-addon">
<xp:text escape="true" id="computedField2"
styleClass="${compositeData.faicon}" tagName="i">
</xp:text>
</span>
<xp:inputText type="text" id="inputText1"
loaded="${!empty compositeData.placeholder}"
value="#{compositeData.dataSource[compositeData.fieldName]}"
required="${compositeData.required}">
<xp:this.attrs>
<xp:attr name="placeholder"
value="${compositeData.placeholder}">
</xp:attr>
</xp:this.attrs>
<xp:this.validators>
            <xp:validateRequired message="#{javascript:compositeData.fieldLabel + ' is required'}"></xp:validateRequired>
          </xp:this.validators>
</xp:inputText>
</div>
<xp:text escape="true" id="computedField3" styleClass="help-block" value="${compositeData.helpText}">
        <xp:this.rendered><![CDATA[#{javascript:getComponent("inputText1").isValid() && compositeData.helpText != null}]]></xp:this.rendered>
      </xp:text>
<xp:message id="message1" for="inputText1" styleClass="help-block"></xp:message>
</div>
</xp:div>
</xp:div>
</xp:view>

Sample Code XPage
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xc:ccLayoutBootstrap>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<div class="page-header">
<h1>
Bootstrap Reusable Fields
<xp:span style="color:rgb(255,255,255)">
</xp:span>
<small>Including Validation</small>
</h1>
</div>
<xc:RBSTextFieldFAComputedText dataSource="#{document1}"
required="true" faicon="fa fa-user" fieldLabel="FirstName"
fieldName="FirstName" helpText="FirstName is a mandatory field"
placeholder="FirstName">
</xc:RBSTextFieldFAComputedText>
<xc:RBSTextFieldFAComputedText dataSource="#{document1}"
required="true" faicon="fa fa-user" fieldLabel="LastName"
fieldName="LastName" helpText="LastName is a mandatory field"
placeholder="LastName">
</xc:RBSTextFieldFAComputedText>
<xp:br></xp:br>
<xp:button value="Save" id="button1"
styleClass="btn btn-primary">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:saveDocument></xp:saveDocument>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:this.facets>
</xc:ccLayoutBootstrap>
</xp:view>

Final Result



There are several other possibilities / methods to add validation to an XPages application including Bootstrap. During the last periode I took a closer look at some of these possibilities / methods like Nod and BootstrapValidator v0.5.2 but finally I ended up with the above validation method. 
At the moment I'm working on a first setup with AngularJS Form Validation. More on this in a later blog post.

No comments:

Post a Comment