重新编译angular指令以编程方式添加ng-module和ng-change

时间:2013-11-06 21:45:29

标签: javascript angularjs angularjs-directive

我想知道我是否做得对。

序言 我开发了一个Typeahead类,它消耗资源并将结果存储在自身中。该类或多或少具有以下结构:

  • 输入:存储搜索文本的位置。
  • list:存储结果的位置。
  • 更改:每次输入更改时执行的功能。
  • 游标:跟踪当前悬停/选定元素的函数。

问题是,如果我想将所有必需的属性附加到输入,代码看起来很臃肿:

<input 
  type="text"
  ng-model="myTa.input"
  ng-change="myTa.change();"
  ng-keyup="myTa.cursor()"
  .... 
/>

我想要完成的是一个只需要Typeahead实例的指令,它会自动将所有必需的属性附加到元素。例如:

<input type="text" my-typeahead="myTa" />

在继续之前,我想说清楚以下内容:

  • 我不想使用模板或templateUrl,因为我想使指令非常灵活,并将它附加到输入,textareas,选择甚至链接。
  • 我不想使用attrs。$ observe或scope。$ watch因为ng-model做得非常出色并完成了我正在寻找的东西。
  • 我知道root元素中的新元素将在没有任何技巧的情况下编译,但父元素本身不会编译新的指令。 (这很有意义)

现在,如果我这样做,我会在地狱里燃烧:

angular
.module('myTypeaheadDirective', [])
.directive('myTypeahead', function($compile, $rootScope) {
    return {
        restrict: 'A',
        scope: {
            typeahead: '=myTypeahead'
        },
        compile: function() {
            return {
                pre: function precompile(scope, element, attrs) {
                    var installedAttribute = 'my-typeahead-installed';

                    if ( angular.isUndefined( element.attr( installedAttribute ) ) ) {
                        element.attr('ng-model', 'typeahead.input');
                        element.attr('ng-change', 'typeahead.change()');
                        element.attr( installedAttribute, true );
                        $compile(element)(scope.$parent);
                    }
                }
            }
        }
    }
});

解释代码:

指令预编译过程检查它是否已经安装,否则它将进入无限循环。

在条件中我添加了尽可能多的指令。

请注意,我正在使用ng-model =“typeahead.input”,但这是一个独立的范围,因此我可以使用不同的typeahead实例进行多个输入。

在附加新指令之​​后,我使用$ compile服务使用父作用域重新编译元素(因此它可以访问原始的typeahead实例)。

我的问题是:

  • 我在这里做的是天真的吗?
  • 有更好的方法吗?
  • 重新编译元素会导致性能问题吗?
  • 以这种方式访问​​父作用域会导致问题吗?

非常感谢您抽出宝贵的时间:)

1 个答案:

答案 0 :(得分:0)

由于您传递到隔离范围的内容可以很容易地从属性值中使用...可以删除隔离范围,然后指令范围将是父级的范围。

要从属性设置typeahead对象,只能执行以下操作:

var typeahead= attrs.myTypeahead;
element.attr('ng-model', typeahead+'.input');