Copied to clipboard

Flag this post as spam?

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


  • ssougnez 93 posts 319 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 93 posts 319 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 206 posts 510 karma points c-trib
    Mar 05, 2019 @ 01:36
    Dan White
    0

    Could you provide an example how you got it working?

  • ssougnez 93 posts 319 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.

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies