Как передать 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); // ???
}
Ответы
Ответ 1
Довольно просто, что вам нужно сделать, это получить доступ к элементу, вставив $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:)
Ответ 2
Сначала я отмечаю, что ваш контроллер не объявлен в модуле, поэтому он не вызывается. (может также захотеть переименовать его, чтобы он не запутывал
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, вы передаете "список" как 2-сторонний параметр привязки здесь, поэтому, если вы хотите передать другой аргумент в качестве параметров, просто передайте его, как ваш параметр "list" в изолированной области,
Вам также не следует назначать непосредственно ng-model или param, которые вы передаете, а скорее "дочернему" элементу объекта, или вы увидите странное поведение, так как ваш локальный объект будет теневать исходный объект родительской области.
Таким образом, вы можете передать 'model.list' в качестве параметра 'list', а затем изменить "список" в локальной области, который будет изменять "model.list" в родительской области.
если вы передадите "список" и измените его в локальной области, он будет переопределять список в родительской области и, вероятно, не получит ваше двухстороннее связывание, которое вы ожидаете.
Ответ 3
Если вы хотите повлиять только на модельное значение, метод $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);
}
};
});