Angular - 将指令附加到重复元素

时间:2015-09-08 18:35:33

标签: angularjs

我是Angular的新手,并且正在使用包含一些现有JavaScript代码的应用。在循环内部,app会附加文件输入按钮,这些按钮会添加到视图中的表行中,如下所示:

cellSeq.innerHTML = cellSeq.innerHTML + 
  '<input type="file" name="f" multiple="multiple" file-bind="" id="my-files-input-' + 
     counter + '">';

因此,通过将counter变量添加到其ID,每个表行上的按钮都是唯一的。我有一个名为file-bind的文件读取指令,我可以附加到一个按钮(没有counter),它处理输入读取的文件。

测试中,这适用于单个按钮,我只是手动粘贴到HTML中(其ID上没有计数器变量):

<input type="file" name="f" multiple="multiple" file-bind="" />

这里是文件阅读指令签名(不太令人兴奋):

angular.module('myApp').directive('fileBind', function() {
  'use strict';
  return function(scope, element, attrs) {
    element.bind('change', function(evt) { 
    //  ...read files

我怀疑问题与我创建指令的方式有关。我想要做的是将我的file-bind指令绑定到每个这些独特的按钮,并在读取文件后更新视图的相应部分。

如何为每个按钮添加一个唯一的指令(就执行上下文而言)?

编辑似乎我需要一个compile函数,因为重复元素是在纯JavaScript中创建的。我在哪里放置编译函数,假设我的指令返回一个函数(而不是一个对象,我可以放置&#39; compile:function()...&#39;)?

1 个答案:

答案 0 :(得分:1)

当使用jQuery以编程方式向DOM添加新的html而不是使用angular(通过ng-repeat,ng-if等)添加它时,Angular很幸福地发现任何事情都发生了变化并且需要相应地做出响应。

因此,您需要在新添加的HTML上调用$ compile以警告Angular它需要重新解析模板并正确编译和链接任何找到的指令。

为了做到这一点,你需要将要编译的元素和元素的范围都传递给$compile()

cellSeq.innerHTML = cellSeq.innerHTML + 
  '<input type="file" name="f" multiple="multiple" file-bind="" id="my-files-input-' + 
 counter + '">';

var element = angular.element(cellSeq);
var scope = element.scope();
$compile(element.contents())(scope);

以上假设您在可以注入$compile(角度控制器)的上下文中使用jQuery。但是,这很可能不是您的用例。如果您要在外部托管组件(例如插件)中通过jQuery添加html,则必须获得更多创意,因为您必须检索$injector实例,以便可以访问$compile

var outerEl = document.getElementById('outer');
outerEl.innerHTML = counter + '<input type="file" name="f" 
    multiple="multiple" file-bind="" id="my-files-input-' + 
counter + '">';

var element = angular.element(outerEl);
var scope = element.scope();

// retrieve the default injector instance
var $injector = angular.injector(['ng']);   

$injector.invoke(["$compile", "$rootScope", function($compile, $rootScope) {
    var $scope = scope || $rootScope;

    $compile(element.contents())($scope);
    $scope.$digest(); 
}]);

你可以看到这个plunkr

如果您的元素不包含范围,则您需要冒泡到$rootScope,因为您必须有$compile的范围才能运行。

我们需要在这个场景中编译后调用$scope.$digest(),因为我们在正常的摘要周期之外从jQuery调用$compile。因此,如果未调用$digest,则无法正确刷新模型绑定。

正如您所看到的,这只是添加一些HTML的很多复杂功能!最好的方法是始终在一个角色中思考。尽可能使用适当的角度工具,指令来管理DOM操作。