Question

I don't know if this has been discussed in the past posts but I could not find anything similar so here goes my question: I have 14 fields on a custom control. Now on a particular condition during the workflow I need to ensure that the first 6 fields should be required (which can be done by using the required validator) and out of the other 8 fields the user should be forced to enter at least 2 fields. How can I achieve this? I am using server side validation for all fields with the property "disableClientSideValidation" set to true. I am not sure if a custom validator can be used in this context and if YES then how?

Was it helpful?

Solution

In your case, you'd use the validateExpression. The SSJS code there has to return true or false. Within the code you can access other fields with getComponent("otherFieldName").getSubmittedValue() and test this way how many fields are filled. In case of 0 or 1 return false and otherwise true.

The validateExpression gets executed only if field is not empty. So, add the validationExpression to one of your first 6 required fields and add there the validateRequired too.

Example:

 <xp:inputText
    id="inputRequired1"
    value="#{...}"
    disableClientSideValidation="true">
    <xp:this.validators>
        <xp:validateRequired message="field is required"></xp:validateRequired>
        <xp:validateExpression message="please, fill at least two fields">
            <xp:this.expression><![CDATA[#{javascript:
            num = 0;
            for (i = 1; i <= 8; i++) {
                if (getComponent("inputText" + i).getSubmittedValue() !== "") {
                    num++;
                }
            }
            if (num < 2) {
                return false;
            }
            return true}]]></xp:this.expression>
        </xp:validateExpression>
    </xp:this.validators>
 </xp:inputText>
 <xp:inputText
    id="inputText1"
    value="#{...}">
 </xp:inputText>
 <xp:inputText
    id="inputText2"
    value="#{...}">
 </xp:inputText>
 ... 

OTHER TIPS

The above mentioned solution is one way to get the handle of validations(there are many), however tis in my opinion not the best solution, since you must validate and write code in each input control. If you want you can do it my way but you have to redo your validations and put it all in one ssjs function which is in the end easier to control. I've put the example code, which is obviously not perfect and is intended to quickly show what I mean. If you choose to go this way then I suggest you wrap you functions and make them dynamic as much as possible. So to answer the question. The validation ssjs function is where you condition your validations based on your business logic.

  1. when submitting your form use an action group.

    <xp:eventHandler id="ehButtonSave"
        refreshMode="partial" submit="true" event="onclick"
        refreshId="somePanelId" >
    
        <xp:this.action>
            <xp:actionGroup>
                <xp:this.condition>
                    <!-- here you validate your fields. Look at number 2 for example -->
                    <!-- this validation function must return true or false which defines if the rest of the code in action group will be executed and the form submitted-->
                    <![CDATA[{javascript:validate("componentValidationErrorDsp");}]]>
                </xp:this.condition>
                <xp:executeScript>
                    <xp:this.script>
                        <![CDATA[#{javascript:
                            <!-- here you can do something with your document -->
                            someSSJSFunction(document1.getDocument());
                        }]]>
                    </xp:this.script>
                </xp:executeScript>
    
                <xp:save></xp:save>
    
            </xp:actionGroup>
        </xp:this.action>
    
        <xp:this.onComplete>
            <![CDATA[XSP.partialRefreshPost('#{id:someInnerPanelId}',{})    ;]]>
        </xp:this.onComplete>
    </xp:eventHandler>
    
  2. Validation example

    var validate = function(dspErrControlName){
    
        var dspErrControl = getComponent( dspErrControlName);
        var inputField = getComponent("InputText1");
        if(isEmpty(inputField.getValue()){
            // here is where you push the validation message back to the displayErrors xsp control.
            var msgObj = new javax.faces.application.FacesMessage(javax.faces.application.FacesMessage.SEVERITY_ERROR, "validation message", "validation message");
            facesContext.addMessage(dspErrControl.getClientId(facesContext), msgObj);
    
            //and here is a little trick to color your inputs so the user can see where exactly is the problem. 
            //What you do is you set the attribute aria-invalid of the input text component to true. Which you can handle with your CSS to become red or something. 
            //CSS example: [aria-invalid=true] { background-color: #fee; border-color: red; }
            var inpuId=getClientId("InputText1");
            view.postScript("dojo.attr(dojo.byId('"+inputId+"'), 'aria-invalid', 'true');")
        }
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top