如何将NgModelController传递给指令控制器?

时间:2015-01-05 19:54:18

标签: angularjs angularjs-directive angularjs-scope

我可以将NgModelController传递给指令控制器吗?这是必需的,所以我可以为控制器中的模型赋值。

此示例不起作用:

   angular
     .module('directives.selectBox', [])
     .directive('selectBox', selectBox);  

    function selectBox() {
        return {
          restrict   : 'E',
          require    : 'ngModel',
          scope      : {
             list     : '=',
          },
          replace     : true,
          templateUrl : 'common/directives/selectBox/selectBox.html',
          controller :  SelectBoxController,
        };
    }  
    function SelectBoxController(ngModel) {
       ngModel.$setViewValue(10); // ???
    }

3 个答案:

答案 0 :(得分:26)

实际上非常简单,您需要做的是通过将$element注入您的控制器然后调用其上的.controller()函数来访问该元素。

angular
   .module('directives.selectBox', [])
   .directive('selectBox', selectBox);  

function selectBox() {
    return {
      restrict   : 'E',
      require    : 'ngModel',
      scope      : {
         list     : '=',
      },
      replace     : true,
      templateUrl : 'common/directives/selectBox/selectBox.html',
      controller :  SelectBoxController,
    };
}  
function SelectBoxController($element) {
   var ngModel = $element.controller('ngModel');
   ngModel.$setViewValue(10); // ???
}

Angular 1.5更新

请注意,在AngularJS 1.5中,除了现有的component()函数之外,还添加了新的directive()函数。此函数将configuratoin对象作为第二个参数,允许您直接指定所需的控制器,然后将其绑定到组件的控制器。

再次在同一个例子下面,但作为组件。

angular
   .module('directives.selectBox', [])
   .component('selectBox', 
        {
            controller: SelectBoxController,
            controllerAs: 'vm',
            templateUrl : 'common/directives/selectBox/selectBox.html',
            bindings: {
                list: '=' // though '<' would be better
            }, 
            require: {
                ngModel: '='
            },
            // replace: true ==> No longer possible with component
        }
    );  

function SelectBoxController($element) {

    $onInit() {
        // This function is called automatically whenever the controller is ready
        this.ngModel.$setViewValue(10); // ???
    }
}

我希望我输入好了,这个小小的textarea几乎不是IDE:)

答案 1 :(得分:0)

首先我注意到你的控制器没有在模块中声明,所以它没有被调用。 (可能还想重命名它以免混淆

angular
     .module('directives.selectBox', [])
     .controller('SelectBoxController',SelectBoxController)
     .directive('selectBox', selectBox);

该指令采用ng-model。然后你可以使用指令的link函数中的$ scope.ngModel来访问它。

function selectBox() {
        return {
          restrict   : 'E',
          require    : 'ngModel',
          scope      : {
             list     : '=',
          },
          replace     : true,
          templateUrl : 'common/directives/selectBox/selectBox.html',
          controller :  SelectBoxController,
          link: function($scope, $element, $attr, ngModel) {

                $scope.ngModel.$setViewValue(10);
           }
        };

这里甚至不需要控制器。 请注意,您不一定需要ngModel,这里已经将'list'作为双向绑定参数传递,因此如果您想将另一个参数作为参数传递,只需将其传递给隔离范围内的'list'参数即可。 您也不应该直接分配给您传递的ng-model或param,而是分配给对象的'child'元素,否则您将看到奇怪的行为,因为您的本地对象将遮蔽父作用域的原始对象。

因此,您可以将'model.list'作为'list'参数传递,然后在本地范围中修改'list',这将修改父范围中的'model.list'。 如果您传递'list'并在本地范围内修改它,它将覆盖父范围中的列表,并且可能无法获得您期望的双向绑定。

答案 2 :(得分:0)

如果您只想影响模型值,$ parse方法最适合您,因为它提供了与外部作用域和编写代码进行通信的常用方法,这不依赖于新的作用域创建。

angular.directive('selectBox', function($parse){
    return {
       // your directive stuff
       link: function(scope, iElem, iAttrs){
           var angularVarSetter = $parse(iAttrs.ngModel).assign;
           // in case of no own scope.
           angularVarSetter(scope, 100500);
           // in case of new scope
           angularVarSetter(scope.$parent, 100500);
       }
    };
});