How to trigger DataBinding Validation for all Controls?

Kai picture Kai · Dec 10, 2014 · Viewed 8.8k times · Source

I have an OpenUI5 form consisting of a number of Inputcontrols. These Inputcontrols are bound to a model using the OpenUI5 DataBinding as described in the documentation. For example:

new sap.m.Input({                           
    value: {
        path: "/Position/Bezeichnung",
        type: new sap.ui.model.type.String(null, {
            minLength: 1,
            maxLength: 128
        })
    }
}) 

As in the example above I'm using constraints on the stringlength. When a User changes the Value of the Input, the Validation is triggered and according to the Validationresult one of the functions descripted here is called. In these functions I'm setting the ValueState of the control like this:

setupValidation: function() {
    var oCore = sap.ui.getCore();
    oCore.attachValidationError(function (oEvent) {
        oEvent.getParameter("element").setValueState(sap.ui.core.ValueState.Error);
    });
    oCore.attachValidationSuccess(function (oEvent) {
        oEvent.getParameter("element").setValueState(sap.ui.core.ValueState.None);
    });
    oCore.attachFormatError(function (oEvent) {
        oEvent.getParameter("element").setValueState(sap.ui.core.ValueState.Error);
    });
    oCore.attachParseError(function (oEvent) {
        oEvent.getParameter("element").setValueState(sap.ui.core.ValueState.Error);
    });
},

Let's assume the bound model variable is initial. I'm loading the view, the property value is parsed and displayed as empty. The Validationerror/Parseerror method is not called although the constraints are not met. This seems to be standard behaviour of OpenUI5. Only changes in the Control will be a validated.

Now let's assume I've a submit button and the Value of the Inputcontrol is still empty. When the user hits the submit button I'd like to trigger the DataBinding Validation for all childcontrols of my view. This would validate the above mentioned input and would result in an errorstate.

My question is: How can I trigger the databinding validation for all childcontrols of my view?

There is another question on SO where the poster asks for a way to define required fields. The proposed solution is to call getValue() on the control and validate the value manually. I think this is kind of cumbersome as formating and constraint information and logic is already present.

Answer

Kyle picture Kyle · May 20, 2017

I suggest looking into field groups.

An example here in the UI5 docs

Field Groups allow you to assign group IDs to the input fields. Then you can call all of the input fields at once. You can set the name property and required property on each <Input> separately in your view, allowing you to handle some logic when you perform validation.

You can call this.getView().getControlsByFieldGroupId("fieldGroupId"), which will return an array of the input controls. Then you can loop through the controls, pass them through your logic, and use setValueState() to show the results.

Or, you can assign the validateFieldGroup event on the parent container, which is usually a form, but can be anything like a <VBox> that contains the controls. When the users focus moves out of the field group, the event is fired. You can then use the event handler in your controller to perform the validation.

In your case, I would assign a press event to your submit button, and in the handler, call the field group by ID and loop through the controls. At the end of your function, check to see if all fields are validated before continuing.

View

<Input name="email" required="true" value="{/user/email}" fieldGroupIds="fgUser"/>
<Input name="firstName" required="false" value="{/user/firstName"} fieldGroupIds="fgUser"/>
<Button text="Submit" press="onSubmit"/>

Controller

onSubmit: function() {
    var aControls = this.getView().getControlsByFieldGroupId("fgUser");
    aControls.forEach(function(oControl) {
        if (oControl.getRequired()) {
            //do validation
            oControl.setValueState("Error");
            oControl.setValueStateText("Required Field");
        }
        if (oControl.getName() === "firstName") {
            //do validation
            oControl.setValueState("Success");
        }
     });
     var bValidated = aControls.every(function(oControl) {
         return oControl.getValueState() === "Success";
     });
     if (bValidated) {
         //do submit
     }
}