Domanda

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.

È stato utile?

Soluzione

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" />
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top