Angular Directive:在编译时在现有模板元素

时间:2015-12-03 21:12:39

标签: javascript angularjs angularjs-directive

简而言之,我们的想法是不必在每个ng-class={'has-error': 'formName.inputName.$invalid'}

上手动添加form-group来简化模板操作

所以我想创建一个指令,生成一个将添加到模板元素的字符串。该字符串是ng-class属性,带有表达式

我认为创建一个在编译阶段添加ng-class属性的快速指令就足够了,但它似乎并没有削减它。

指令定义对象

{
    restrict: 'C',
    compile: function(tElement, tAttrs) {
        var $elem = angular.element(tElement),
            formName = $elem.parents('[ng-form]').length ? $elem.parents('[ng-form]').attr('ng-form') : $elem.parents('form').attr('name'),
            controlName = $elem.find('.form-control').attr('name');

        $elem.attr('ng-class', '{"has-error": ' + formName + '.' + controlName + '.$invalid}');

        console.log('added ng-class attr', $elem.attr('ng-class'));
    }
}

Plunk here

查看控制台

  

第一个form-group动态添加了ng-class属性   与之相关的表达是正确的   但ng-class指令永远不会执行

     

第二个form-group在模板中手动添加了ng-class属性,并按预期工作,显然

-

我在这里缺少什么?

2 个答案:

答案 0 :(得分:6)

管理以使其工作而不添加额外的观察者(授予,ng-class使用观察者,但在测试建议的解决方案后,我看到观察者数量增加)

我必须在postLink中编译新的DOM元素,但为了避免递归,我需要删除指令本身。这使我无法重用类名,例如“form-group”

这是工作指令

function bsFormClass($compile) {
  return {
    restrict: 'A',

    compile: function (tElement) {

        var $elem = angular.element(tElement),
            controlName = $elem.find('.form-control').attr('name');

        if(!controlName) { return; }

        var formName = $elem.parents('[ng-form]').length ? $elem.parents('[ng-form]').attr('ng-form') : $elem.parents('form').attr('name');

        $elem.attr('ng-class', '{"has-error": ' + formName + '.' + controlName + '.$invalid}');
        $elem.removeAttr('bs-form-class');

        return {
            post: function(scope, elem, attrs) {
                $compile(elem)(scope);
            }
        }
    }
  }
}

感谢您帮助所有

答案 1 :(得分:3)

无法将指令添加到当前元素!

在您的情况下,解决方案很简单;只需观察适当的表达式并根据需要添加类:

function formGroupClass () {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {
            var formName = elem.parents('[ng-form]').length ? elem.parents('[ng-form]').attr('ng-form') : elem.parents('form').attr('name'),
                controlName = elem.find('.form-control').attr('name');

            scope.$watch(formName + '.' + controlName + '.$invalid', function(newval) {
              elem.toggleClass('has-error', !!newval);
            });
        }
    };
}

ng-class无论如何都会添加一个手表...请参见forked plunk:http://plnkr.co/edit/oKa6CKFoF1T5WoDzIPkI?p=preview