it-swarm.com.ru

Как передать NgModelController в директиву контроллера?

Могу ли я передать 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); // ???
    }
14
Miron

На самом деле довольно просто, что вам нужно сделать, это получить доступ к элементу, вставив $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); // ???
    }
}

Надеюсь, я все напечатал, эта крошечная текстовая область вряд ли является IDE :)

25
Robba

Вначале отмечу, что ваш контроллер не объявлен в модуле, поэтому он не вызывается. (может также захотеть переименовать его, чтобы это не смущало

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

Директива принимает модель ng. затем вы можете получить к нему доступ, используя $ 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.list" в качестве параметра "list", а затем изменить "list" в локальной области видимости, который изменит "model.list" в родительской области видимости. если вы передадите 'list' и измените его в локальной области, он переопределит список в родительской области и, вероятно, не получит ожидаемую двустороннюю привязку.

0
MrE

Если вы хотите повлиять только на значение модели, метод $ 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);
       }
    };
});
0
Valery Kozlov