Developer forum

Forum » Development » Custom validator for code first items

Custom validator for code first items

Hans Kloppenborg
Reply

Hello,

We have been trying to create a custom validator for code first items, but are struggling to get something elegant to work. 

The code for a working version was like this:
 

using Dynamicweb.Content;
using Dynamicweb.Content.Items.Editors;
using Dynamicweb.Extensibility.AddIns;
using Dynamicweb.SystemTools;

namespace Dynamicweb.Validation
{
    public class CompanyValidator : Validator
    {
        private static readonly IHttpHelper _helper = AddInManager.CreateAddInInstance<IHttpHelper>();

        /// <summary>
        /// Validates if the value is a integer pageId value and if the give page is of type PartnerArticle
        /// </summary>
        /// <param name="context"></param>
        /// <returns>true if selected page is a PartnerArticle, false in all other cases</returns>
        public override bool Validate(ValidatorContext context)
        {
            bool result = false;
            if (context != null && context.Value != null && int.TryParse(context.Value.ToString(), out int pageId))
            {
                var pageService = new PageService();
                var page = pageService.GetPage(pageId);
                if (page != null && page.ItemType == "PartnerArticle")
                {
                    result = true;
                }
            }
            return result;
        }

        public override string RenderValidator(string context, EditFormField field)
        {
            if (string.IsNullOrEmpty(ErrorMessage))
            {
                ErrorMessage = $"Selected page must be a PartnerArticle for field {field.Name}";
            }

            var text = ErrorMessage;
            if (_helper != null)
            {
                text = _helper.JavaScriptStringEncode(text);
            }

            return $"{context}.addValidator(new Dynamicweb.Validation.CompanyValidator('{field.Id}', '{text}'));";
        }
    }
}

With the following javascript added to Admin/Content/JsLib/dw/Validation.js

Dynamicweb.Validation.CompanyValidator = function (target, errorMessage) {
  this.set_target(target);
  this.set_errorMessage(errorMessage);
}

Dynamicweb.Validation.CompanyValidator.prototype = new Dynamicweb.Validation.SimpleValidator();

Dynamicweb.Validation.CompanyValidator.prototype.beginValidate = async function (context, onComplete) {
  var result = {
    isValid: false,
    errorMessage: this.get_errorMessage()
  };

  var t = context.manager.getField(this.get_target());
  var v = context.manager.getValue(this.get_target());
  var pageId = v.split('?')[1].split('=')[1];
  if (t) {
    let response = await fetch('/api/partner/validate/' + pageId, {
      method: 'GET'
    })
    if (response.ok) {
      let json = await response.json();
      result.isValid = json.result;
    }

    if (!result.isValid) {
      try {
        if (Dynamicweb.Validation.setFocusToValidateField) {
          t.focus();
        }
      } catch (ex) { }
    }
  }

  return onComplete(result);
}

The problem is that this means a change to a Dynamicweb javascript file which will be overwritten with every core update.

I tried to circumvent this by using a Dynamicweb.Validation.CustomValidator like

{context}.addValidator(new Dynamicweb.Validation.CustomValidator('{field.Id}', '{text}',validateCompany));";

but then I have the issue that I need to inject the javascript function validateCompany somehow, and in that function I no longer have my validation context.manager, which means that getting the values becomes more complex.

Does anyone have an example of a working custom validator for code first items with a solution for the javascript function.

And does anyone know if the "public override bool Validate" backend validation ever gets called, it seemed to me that the only code called was the javascript version of the validation.

Greets Hans


Replies

 

You must be logged in to post in the forum