Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • ssougnez 85 posts 289 karma points c-trib
    Oct 09, 2018 @ 15:17
    ssougnez
    0

    Custom validation for custom property editor

    Hello,

    I'm creating a simple property editor:

    <div>
        <input id="page-url" type="text" class="umb-editor umb-text-string" ng-model="model.value" val-property-validator="validateUrl"  />
    </div>
    

    The code from "validateUrl" is the following:

    this._$scope.validateUrl = () => {
        return {
            isValid: !this._$scope.error,
            errorMsg: "This URL is already associated to another page",
            errorKey: "pageUrlValidation"
        }
    }
    

    Nothing really fancy here but I have a weird behavior. Indeed, with this code, the value of "model.value" is never shown in the "input". Moreover, what I type in it, "model.value" is not updated, it's like "ng-model" was not applied. Therefore, when I try to save the node, the validation function always execute on the same value. I tried to display "model.value" on the page and I can see that the value is never updated.

    The value of "_$scope.error" is updated when the user types in the input.

    Note that if I remove the "val-property-validator" attribute, the "ng-model" applies correctly but then I'm unable to apply custom validation on it.

    When I looked in UmbracoCms repo, I noticed that fields with the validation are often hidden (I didn't check all the files) but I guess it's because the UI forces it...

    Am I missing something here?

  • Jamie Freeman 38 posts 151 karma points
    Oct 10, 2018 @ 10:20
    Jamie Freeman
    0

    have you tried doing something like

    <div ng-scope="model">
      <input id="page-url" type="text" class="umb-editor umb-text-string" ng-model="value" val-property-validator="validateUrl"  />
    </div>
    

    equally (without knowing the rest of the scope) have you tried just value

    <div>
        <input id="page-url" type="text" class="umb-editor umb-text-string" ng-model="value" val-property-validator="validateUrl"  />
    </div>
    
  • ssougnez 85 posts 289 karma points c-trib
    Oct 10, 2018 @ 13:52
    ssougnez
    0

    I'll try that but after some research it turns out it's an Angular issue. When you use a directive that requires "ngModel", you have to use "$parent" in the binding to make it works... I created a custom directive to see what was the issue and solved the issue by using this trick.

  • Dan White 205 posts 508 karma points c-trib
    Mar 05, 2019 @ 01:36
    Dan White
    0

    Could you provide an example how you got it working?

  • ssougnez 85 posts 289 karma points c-trib
    Mar 05, 2019 @ 07:22
    ssougnez
    0

    Hi,

    it's a long time ago so I don't remember well but here are the relevant part of my code. First of all, I changed a bit the purpose of the validator. It just checks whether a boolean is true/false.

    Here is the HTML where I use it:

    <input type="text"
           class="umb-editor umb-text-string"
           ng-model="$parent.$ctrl.model.value"
           property-boolean-validator="$parent.$ctrl.error"
           property-boolean-validation-error-message="This URL is already used by another page."
           property-boolean-validator-key="uniqueUrl" />
    

    The trick here is to use "$parent" in the HTML instead of directly "$ctrl" as AngularJs 1.x as this issue. Note that in the code, I also listen to input event on the textbox with RxJs (to use debounceTime) and change the value of $ctrl.error based on the entered value.

    Now, the code of the directive (it's TS):

    export function PropertyBooleanValidatorDirective(): ng.IDirective {
        return {
            restrict: "A",
            scope: {
                propertyBooleanValidator: '=',
                propertyBooleanValidationErrorMessage: '@',
                propertyBooleanValidatorKey: '@'
            },
            require: ["ngModel", "?^umbProperty"],
            link: (scope: IPropertyBooleanValidatorScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls: ng.IController[]) => {
                var modelCtrl = ctrls[0] as ng.INgModelController;
                var propCtrl = ctrls.length > 1 ? ctrls[1] : null;
    
                if (propCtrl) {
                    scope.$watch(() => scope.propertyBooleanValidator, (nv: boolean) => {
                        modelCtrl.$setValidity(scope.propertyBooleanValidatorKey, !nv);
    
                        if (nv === true) {
                            propCtrl.setPropertyError(scope.propertyBooleanValidationErrorMessage);
                        }
                        else {
                            propCtrl.setPropertyError(null);
                        }
                    });
                }
            }
        }
    }
    

    So basically I just watch the value of the attributes and update the field validity based on its value.

Please Sign in or register to post replies

Write your reply to:

Draft