动态地将ngModel添加到angular指令中的子元素

时间:2015-04-02 09:31:07

标签: angularjs

有一些指令要取消选中以前检查过的群组中的广播:

(function (angular, $) {
    'use strict';

    var radioGroupDirective = function () {
        return {
            restrict: 'EA',
            require: 'ngModel',
            link: function($scope, $element, $attrs, ngModelController) {
                var $radios = $element.find('input[type="radio"]');
                $radios.click(function($event) {
                    var $radio = $($event.target);
                    if ($radio.data('waschecked') == true) {
                        $radio.prop('checked', false);
                        $radio.data('waschecked', false);
                        ngModelController.$setViewValue(null);
                    } else {
                        $radio.data('waschecked', true);
                    }
                    $radio.siblings('input[type="radio"]').data('waschecked', false);
                });
            },
        };
    };

    radioGroupDirective.$inject = [];

    angular.module('radio.group', []).directive('radioGroup', radioGroupDirective); 
})(angular, $);

用法:

<div radio-group ng-model="fruit">
  <input type="radio" ng-model="fruit" value="Apple"/>
  <input type="radio" ng-model="fruit" value="Banana"/>
  <input type="radio" ng-model="fruit" value="Mango"/>
</div>

它工作正常,但我想在子输入中删除重复的ngModel代码。像这样:

<div radio-group ng-model="fruit">
  <input type="radio" value="Apple"/>
  <input type="radio" value="Banana"/>
  <input type="radio" value="Mango"/>
</div>

所以我尝试在编译函数

中动态地将ngModel添加到所有子输入
(function (angular, $) {
    'use strict';

    var radioGroupDirective = function ($compile) {
        return {
            restrict: 'EA',
            require: 'ngModel',
            link: function($scope, $element, $attrs, ngModelController) {
                var $radios = $element.find('input[type="radio"]');
                $radios.click(function($event) {
                    var $radio = $($event.target);
                    if ($radio.data('waschecked') == true) {
                        $radio.prop('checked', false);
                        $radio.data('waschecked', false);
                        ngModelController.$setViewValue(null);
                    } else {
                        $radio.data('waschecked', true);
                    }
                    $radio.siblings('input[type="radio"]').data('waschecked', false);
                });
            },
            compile: function (tElement, tAttrs) {
                var $radios = tElement.find('input[type="radio"]');
                angular.forEach($radios, function(radio) {
                    $(radio).attr('ng-model', tAttrs.ngModel);
                });
                return {
                    pre: function preLink(scope, iElement, iAttrs, controller) {
                    },
                    post: function postLink(scope, iElement, iAttrs, controller) {
                        $compile(iElement)(scope);
                    },
                };
            },
        };
    };

    radioGroupDirective.$inject = ['$compile'];

    angular.module('radio.group', []).directive('radioGroup', radioGroupDirective);

})(angular, $);

但它会导致无限的编译循环和浏览器的死机

2 个答案:

答案 0 :(得分:1)

您尝试从链接函数再次编译整个指令(radioGroup),因此它会导致无限循环。 而是只编译输入:

angular.forEach($radios, function(radio) {
    $compile(radio)(scope);
});

请参阅此plunker

答案 1 :(得分:1)

此指令的完整工作plunker(对于能够发现它有用的人)

var radioGroupDirective = function ($compile) {
        return {
            restrict: 'EA',
            require: 'ngModel',
            compile: function (tElement, tAttrs) {
                var $radios = tElement.find('input');
                angular.forEach($radios, function(radio) {
                    $(radio).attr('ng-model', tAttrs.ngModel);
                });
                return {
                    pre: function preLink(scope, iElement, iAttrs, controller) {
                    },
                    post: function postLink(scope, iElement, iAttrs, controller) {
                        angular.forEach($radios, function(radio) {
                          $compile(radio)(scope);
                        });
                        $($radios).click(function($event) {
                          var $radio = $($event.target);
                          if ($radio.data('waschecked') == true) {
                              $radio.prop('checked', false);
                              $radio.data('waschecked', false);
                              controller.$setViewValue(null);
                          } else {
                              $radio.data('waschecked', true);
                          }
                          $radio.siblings('input[type="radio"]').data('waschecked', false);
                      });
                    },
                };
            },
        };
    };

radioGroupDirective.$inject = ['$compile'];

angular.module('radio.group', []).directive('radioGroup', radioGroupDirective);