Viewing File: /usr/local/cpanel/share/libraries/cjt2/src/directives/validateEqualsDirective.js

/*
# cjt/directives/validateEqualsDirective.js          Copyright 2022 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

/* global define: false */

// TODO: Maybe move to the validators folder

define(
    [
        "angular"
    ],
    function(angular) {

        "use strict";

        // Get the current application
        var module = angular.module("cjt2.directives.validateEquals", []);

        /**
         * Directive that compares the field value with another value.
         * @attribute {String}  validateEquals Model to compare against.
         * @example
         *
         * For an optional fields comparison:
         * <form name="form">
         * <input name="password" ng-model="password">
         * <input name="confirm" ng-model="confirm" validate-equals="form.password">
         * <button type="submit" ng-disabled="form.$invalid">Submit</button>
         * </form>
         *
         * For an required fields comparison:
         * <form name="form">
         * <input name="password" ng-model="password" required>
         * <input name="confirm" ng-model="confirm" validate-equals="form.password">
         * <button type="submit" ng-disabled="form.$invalid">Submit</button>
         * </form>
         *
         * Note: If the field being watch is required and either it or the field with this
         * directive attached is empty, it makes the form invalid.
         */
        module.directive("validateEquals", function() {
            return {
                require: "ngModel",
                link: function(scope, elm, attrs, ngModel) {

                    /**
                     * Validate that the value is equal to the requested value
                     * @param  {String} value Value to test.
                     * @return {Boolean}      true if the passed in value is equal to the registered value.
                     */
                    ngModel.$validators.validateEquals = function validateEquals(value) {

                        var ngOtherModel = getNgOtherModel();
                        if (!ngOtherModel) {

                            // Early in the page life cycle
                            return true;
                        }

                        var thisIsEmpty = ngModel.$isEmpty(value);
                        var otherIsEmpty = ngOtherModel.$isEmpty(ngOtherModel.$viewValue);
                        if (thisIsEmpty && otherIsEmpty) {

                            // If both inputs are empty, it's valid if the other field is not required.
                            return !ngOtherModel.$validators.required;
                        } else {

                            return (

                                /**
                                 * If we have an asyncValidator in progress then we should validate against the
                                 * viewValue to present immediate results. This validator will be re-evaluated if
                                 * the modelValue changes after the asyncValidation because of the $watchGroup.
                                 *
                                 * We should also use the viewValue if the other model is marked as invalid, to
                                 * make sure that we're validating against an actual value instead of undefined.
                                 * While these results don't actually matter because the other model will need to
                                 * be modified for it to be valid, it would feel awkward without feedback from
                                 * this validator.
                                 */
                                (ngOtherModel.$pending || ngOtherModel.$invalid) ?
                                    (value === ngOtherModel.$viewValue) :
                                    (value === ngOtherModel.$modelValue)
                            );
                        }
                    };

                    /**
                     * Check for changes on the comparison value and validate if changed. We watch the
                     * viewValue to ensure that users get immediate feedback before validators run. We
                     * watch the modelValue to ensure that models that don't pass validation or get
                     * transformed by parsers/formatters are properly validated.
                     */
                    scope.$watchGroup([
                        function() {
                            var ngOtherModel = getNgOtherModel();
                            return ngOtherModel && ngOtherModel.$viewValue;
                        },
                        function() {
                            var ngOtherModel = getNgOtherModel();
                            return ngOtherModel && ngOtherModel.$modelValue;
                        }
                    ], function() {
                        ngModel.$validate();
                    });

                    // We need to use this getter for form controls that are added later in the life cycle.
                    var _ngOtherModel;
                    function getNgOtherModel() {
                        if (!_ngOtherModel) {
                            _ngOtherModel = scope.$eval(attrs.validateEquals);
                        }
                        return _ngOtherModel;
                    }
                }
            };
        });
    });
Back to Directory File Manager