1

我正在尝试在我的应用程序的元素中动态插入一个ng-options指令<select>,这些元素都有自己的类名和其他指令(比如ng-if等等)。

<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) });
});

密码笔

这个想法是my-directive应该被替换,ng-options并且元素应该仍然像应用到它的所有其他指令一样正常运行。

我不明白为什么ng-model不更新,因为指令的范围是父范围(scope: false)。我试图在compile指令的步骤中进行 DOM 修改,但$scope.items变得未知,甚至没有填充下拉菜单。

4

1 回答 1

0

您的主要问题是您需要为指令设置非常高的优先级,以使其编译功能在 ngModel 之前执行(以及 ngIf 也是)。为此,不要手动编译,而是实现指令的编译功能:

.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

于 2015-12-08T10:58:44.613 回答