1

我试图在我的应用程序中动态插入ng-options指令,这些指令都在<select>之间,它们都有自己的类名和其他指令(如ng-if等)。Dynamic AngularJS指令

<div ng-app="app" ng-controller="ctrl"> 
    <select ng-model="model" class="myClass" ng-if="condition || true" my-directive> 
    </select> 
    <pre>{{ model | json }}</pre> 
</div> 

angular 
.module('app', []) 
.directive('myDirective', function($compile) { 
    return { 
    restrict: 'A', 
    scope: false, 
    link: function($scope, $elem, $attr) { 
     $scope.items = [{ label: "foo", value: "foofoo"}, 
         { label: "bar", value: "barbar"}]; 
     $elem.removeAttr('my-directive'); // Prevents infinite loop 
     $elem.attr('ng-options', 'item as item.label for item in items'); 
     $compile($elem)($scope); 
    } 
    } 
}) 
.controller('ctrl', function($scope) { 
    $scope.model = null; 
    $scope.$watch('model', function(val) { console.log('•', val) }); 
}); 

Codepen

的想法是,my-directive应该由ng-options更换和元素还是应该表现得像正常,应用到它的所有其他指令。

我不明白为什么ng-model没有得到更新,因为指令的作用域是父作用域(scope: false)。我试图在指令的compile步骤中对DOM进行修改,但$scope.items未知,并且下拉列表甚至没有填充。

回答

0

你的主要问题是你需要设置你的指令的高优先级,以使它的编译函数在ngModel的一个(也是ngIf's)之前执行。对于这一点,不要手动编译,但执行的指令的编译功能:

.directive('myDirective', function($compile) { 
    return { 
     priority: 10000, 
     terminal: true, 
     link: function(scope, element) { 
     element.attr('ng-options', 'item as item.label for item in items').removeAttr('my-directive'); 
     $compile(element)(scope); 
     } 
    } 
    }) 

您还需要记住的是,如果你使用的是创建新范围(如ngIf,ngInclude等)的指令,你可能会得到当模型不会更新时出现意外行为,因为Angular会将值写入子范围模型。在您的演示中,我使用$parent来明确指出适当范围,但最好使用controllerAs表示法来消除此类问题。

你也不想在指令链接函数中设置项目,但我想这只是为了演示的目的,你应该将它移动到控制器。

演示:http://codepen.io/anon/pen/KVwQYr?editors=101

+0

我正忙着编制一个答案时,你打我吧。只有一个问题,为什么你需要'ng-if =“条件|| true”'指令来使它工作?请参阅第一个例子,其中存在'ng-if =“condition || true”'。然后在第二个例子中'ng-if =“条件|| true”'不存在,并且'select'选项没有被填充。 1. https://jsfiddle.net/vg2wgamg/ 2. https://jsfiddle.net/2qzjkpqL/我总是可以问这个问题,让你在那里回答它? –

+0

@TjaartvanderWalt这真的很棘手的问题。我不清楚自己是什么导致了这种行为,但是它与ngIf创建的附加嵌套范围有关。我找到的解决方案是添加'terminal:true'指令来防止进一步编译(?)。我还发现有必要在链接函数中手动编译元素。检查更新的演示。 – dfsq

+0

好的。我测试过了,你以前的例子工作正常,因为它在指令的编译函数中。我不认为你需要手动使用'$ compile'服务,就像你在更新后的代码示例中那样 –