Question

I need a couple of directives performing input field cleanup and validation, just like in this question. All of them are the same except for the cleanup and validation functions themselves and the field name. Currently, I'm copying it like

angular.module('myModule')

.directive('validateFoo', function() {
      return {
        restrict: 'A',
        require: 'ngModel',
        link: function($scope, element, attrs, ngModel) {
            // THESE THREE LINES SHOULD BE ARGUMENTS
            var isValid = isValidFoo;
            var clean = cleanFoo;
            var name = "foo";

            element = $(element);

            var cleanAndValidate = function(x) {
                var y = clean(x);
                var ok = isValid(y);
                ngModel.$setValidity(name, ok);
                return y;
            };

            ngModel.$parsers.push(cleanAndValidate);

            var fix = function() {
                var x = element.val();
                var y = clean(x);
                if (x===y) return y;
                var e = element[0];
                var start = e.selectionStart;
                var end = e.selectionEnd;
                element.val(y);
                var delta = y.length - x.length;
                e.setSelectionRange(start + delta, end + delta);
                return y;
            };

            element.keyup(function() {
                fix();
            });
        }
    };
})

which is obviously a bad idea. I guess I should be able to do it using a closure, but I'd also like to preserve the overall structure (all my files start with angular.module followed by a definition). If I had access to the directive name in the body, I could get the three variables from their defining object.

Était-ce utile?

La solution

All of them are the same except for the cleanup and validation functions themselves and the field name

I think you need to add a scope to your custom directive; then you can pass in the functions and field that need to be processed. Something like this:

.directive('validateFoo', function() {
      return {
        restrict: 'A',
        require: 'ngModel',
        scope : { 
            // DEFINE These Arguments in the scope
            isvalid : "=isvalid",
            clean : "=clean",
            name : "=name"
        }
        link: function($scope, element, attrs, ngModel) {

            element = $(element);

            // modify this method to access your clean/isvalid/name values in the $scope
            var cleanAndValidate = function(x) {
                var y = $scope.clean(x);
                var ok = $scope.isValid(y);
                ngModel.$setValidity($scope.name, ok);
                LOG name, x, y, ok
                return y;
            };

            ngModel.$parsers.push(cleanAndValidate);

            var fix = function() {
                var x = element.val();
                var y = clean(x);
                if (x===y) return y;
                var e = element[0];
                var start = e.selectionStart;
                var end = e.selectionEnd;
                element.val(y);
                var delta = y.length - x.length;
                e.setSelectionRange(start + delta, end + delta);
                return y;
            };

            element.keyup(function() {
                fix();
            });
        }
    };
})

When you use the directive, you can pass in the function and values, sort of like this:

<validate-foo isvalid="isValidFoo" clean="cleanfoo" name="foo" />
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top