20
Jun
2017

Episerver Forms validator with settings

When you have worked with Episerver Forms, you know you can enable validators on a form element. You have the Required validator, the Regular Expression validator, the Email validator and more. Most of these validators have a simple on/off configuration, but when you look at the Regular Expression validator there is a ‘change’ option to set the actual RegEx.

RegularExpressionValidator1RegularExpressionValidator2

How can we create such a validator with settings? The secret is in an interface called IPreviewableTextBox.

We will build a custom validator that checks a string for a minimum length.
To start building our validator we begin with a simple model that will contain the value of our setting.

public class MinimumStringLengthValidationModel : ValidationModelBase
{
    public int MinimumLength { get; set; }
}

Now that we have the model in place, let’s build the actual validator.

Here we will use the IPreviewableTextBox interface. It’s just an empty interface, but the Forms UI will pick it up to render the ‘change’ link and textbox. Since it is a textbox, the value we enter is always a string.

public class MinimumStringLengthValidator : ElementValidatorBase, IPreviewableTextBox
{
        public override bool? Validate(IElementValidatable targetElement)
    {
        int minLength = (this.BuildValidationModel(targetElement) 
            as MinimumStringLengthValidationModel).MinimumLength;

        string submittedValue = targetElement.GetSubmittedValue() as string;
        if (!string.IsNullOrWhiteSpace(submittedValue))
            return new bool?(submittedValue.Length >= minLength);
            
        return new bool?(true);
    }
        
    public override IValidationModel BuildValidationModel(IElementValidatable targetElement)
    {
        var validationModel = 
            base.BuildValidationModel(targetElement) as MinimumStringLengthValidationModel;

        if (validationModel != null)
            validationModel.Message = 
                string.Format(validationModel.Message, validationModel.MinimumLength);

        return validationModel;
                       
    }

    public override void Initialize(string rawStringOfSettings)
    {
        base.Initialize(rawStringOfSettings);
        int minLength = 0;
        this._model = new MinimumStringLengthValidationModel
        {
            MinimumLength = int.TryParse(rawStringOfSettings, out minLength) ? minLength : 0
        };
    }
}

To work with our validator setting we need to override some methods.

First the Initialize method.
This method will receive the value we specified in the validator setting. In our validator, we need to convert it to an integer. If someone entered an incorrect value like ‘abc’ we will convert that to 0.

Next up is the BuildValidationModel method.
We don’t really need to override it, but since I wanted to create a clear validation message that specifies the minimum number of character, I did.

Finally, there is the Validation method.
This is the actual (server side) validation. If the string is at least the specified length it will succeed, else it will fail.
If not value is entered in the form the validator will succeed. We are not checking for a required field here.

Don’t forget to enter the name of the validator and the validation message in the resource file.

<languages>
  <language name="English" id="en">
    <episerver>
      <forms>
        <validators>
          <Alloy.Business.Forms.MinimumStringLengthValidator>
            <displayname>Minimum string length</displayname>
            <message>Please enter at least {0} characters.</message>
          </Alloy.Business.Forms.MinimumStringLengthValidator>
      </validators>
      </forms>
    </episerver>
  </language>
</languages>

Besides the server validation we also need client validation. Therefor we add our new validator to the Episerver Forms validators list.
Be sure to use the full namespace as the validator name.

(function ($) {

    var _utilsSvc = epi.EPiServer.Forms.Utils;

    // extend the EpiForm JavaScript API in ViewMode
    $.extend(true, epi.EPiServer.Forms, {
        /// extend the Validator to validate Visitor's value in Clientside.        
        Validators: {
            "Alloy.Business.Forms.MinimumStringLengthValidator": function (fieldName, fieldValue, validatorMetaData) {
                // this function is used to validate visitor's data value in ViewMode

                if (!validatorMetaData || !validatorMetaData.model || !validatorMetaData.model.minimumLength || fieldValue === "") {
                    // This element is valid
                    return { isValid: true };
                }

                if (fieldValue.length < validatorMetaData.model.minimumLength)
                {
                    var message = _utilsSvc.stringFormat(validatorMetaData.model.message, [validatorMetaData.model.minimumLength])
                    return {isValid: false, message: message };
                }

                return { isValid: true };
            },
        },
    });
})($epiforms || $);

The property validatorMetaData.model contains our validation model. fieldValue is the value entered by the user in the form.

To use the validator, we create a custom element block. In this case I simply inherit from the TextboxElementBlock.
Decorate the element block with the AvailableValidatorTypes and include our custom validator.

[ContentType(
    DisplayName = "My Textbox", 
    GUID = "77e3970b-e9f9-4053-9175-7070201681d4", 
    GroupName = ConstantsFormsUI.FormElementGroup)]
[AvailableValidatorTypes(Include = new [] { typeof(MinimumStringLengthValidator) })]
public class MyTextboxElementBlock : TextboxElementBlock, IElementRequireClientResources
{
    public IEnumerable<Tuple<string, string>> GetExtraResources()
    {
        return new List<Tuple<string, string>>() {
            new Tuple<string, string>("script", "/ClientResources/ViewMode/MinimumStringLengthValidator.js")
        };
    }
}

To load the JavaScript file for client side validation, we need to implement the IElementRequireClientResources interface on our element block. The GetExtraResources method return a list of additional resources load, specifying type and path.

That’s it. Now we can build the form and use our validator.

MinimumStringLengthValidator1

Share

You may also like...