从 AngularJS 中的父控制器调用指令的方法
Calling directive's methods from parent controller in AngularJS
>我正在使用带有别名控制器模式的AngularJS。我无法访问(或者我不知道如何)来自父控制器的指令方法。
我的控制器中有一个函数,应该调用指令方法,但此指令方法在this
控制器值中不可用。
这就是我所拥有的。我做错了什么?
.JS
angular.module('myApp', []).
controller('MyCtrl', function(){
this.text = 'Controller text';
this.dirText = 'Directive text';
this.click = function(){
this.changeText();
}
})
.directive('myDir', function(){
return {
restrict: 'E',
scope: {
text: '='
},
link: function(scope, element, attrs){
scope.changeText = function(){
scope.text = 'New directive text';
};
},
template: '<h2>{{text}}</h2>'
};
});
.HTML
<div ng-app="myApp">
<div ng-controller="MyCtrl as ctrl">
<h1>{{ctrl.text}}</h1>
<my-dir text="ctrl.dirText"></my-dir>
<button ng-click="ctrl.click()">Change Directive Text</button>
</div>
</div>
这里是带有代码的代码笔。
如果你严格想在指令中使用隔离scope
,那么指令方法只能通过使用角度事件来调用,如$broadcast
和$emit
在您的情况下,您需要使用 $broadcast
将事件发送到整个$rootScope
你的代码会变成这样。
工作代码笔
.HTML
<div ng-app="myApp">
<div ng-controller="MyCtrl as ctrl">
<h1>{{ctrl.text}}</h1>
<my-dir text="ctrl.dirText"></my-dir>
<button ng-click="ctrl.click()">Change Directive Text</button>
</div>
</div>
法典
angular.module('myApp', []).
controller('MyCtrl', function($rootScope){
var that = this;
this.text = 'Controller text';
this.dirText = 'Directive text';
this.click = function(){
$rootScope.$broadcast('changeText',{});
}
}).
directive('myDir', function(){
return {
restrict: 'E',
scope: {
text: '='
},
link: function(scope, element, attrs){
scope.changeText = function(){
scope.text = 'New directive text';
};
scope.$on('changeText',function(event, data){
scope.changeText()
});
},
template: '<h2>{{text}}</h2>'
};
});
而不是调用子作用域的方法,你需要广播一个事件,该事件必须由指令作用域侦听,它将在侦听该事件后触发changeText
方法。
注意
使用服务/工厂会是更好的方法。
希望对您有所帮助。谢谢。
可以实现调用指令方法,而无需依赖$broadcast或删除范围隔离。如果页面上有 2+ 个指令实例,到目前为止已经发布在此处的类似方法将中断(它们都将反映相同的更改)。
此代码笔演示了一种更可靠的方法来执行此操作。
angular.module('myApp', [])
.controller('myChat', function($scope) {
function room () {return { accessor:{} }; }
$scope.rooms = { 'RoomA': new room, 'RoomB': new room, 'RoomC': new room };
$scope.addMessageTo = function(roomId, msg) {
if ($scope.rooms[roomId].accessor.setMessage)
$scope.rooms[roomId].accessor.setMessage(msg);
};
$scope.addMessages = function () {
$scope.addMessageTo("RoomA", "A message");
$scope.addMessageTo("RoomB", "Two messages");
$scope.addMessageTo("RoomC", "More messages");
}
}).directive('myChatRoom', function() {
return {
template: '<div>{{room}} message = {{message}}<div />',
scope: { accessor: "=", room: "@" },
link: function (scope) {
if (scope.accessor) {
scope.accessor.setMessage = function(msg) {
scope.message = msg;
};
}
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myChat">
<div ng-repeat="(roomId, room) in rooms">
<div my-chat-room room="{{roomId}}" accessor="room.accessor"></div>
</div>
<button ng-click="addMessages()">Add messages to rooms</button>
</div>
</div>
我有另一种解决方案,它可以让您使用隔离范围而不依赖广播。在javascript中,方法可以像变量一样使用,co你可以简单地将你想要的方法传递给指令。
所以在 HTML 中:
<my-dir text="ctrl.dirText" change-text="ctrl.changeText"></my-dir>
并在指令中
scope: {
text: '=',
changeText: '='
}
这是稍微修改的代码笔,你可以看到我的想法。
编写时,你正在隔离范围:
scope: {
text: '='
},
这是代码的略微修改版本,这次允许您调用指令方法。大多数情况下,我只是在指令中摆脱了'scope'
,并将其更改为在控制器中使用$scope,而不是这个和别名模式。
警告:这可能无法反映正确的行为,关于 哪些变量发生了变化,但通过显示如何回答您的问题 您可以从控制器访问指令的方法。这通常不是 一个好的设计理念..
http://codepen.io/anon/pen/azwJBm
angular.module('myApp', []).
controller('MyCtrl', function($scope){
var that = this;
$scope.text = 'Controller text';
$scope.dirText = 'Directive text';
$scope.click = function(){
$scope.changeText();
}
}).
directive('myDir', function(){
return {
restrict: 'E',
/* scope: {
text: '='
},*/
link: function(scope, element, attrs){
scope.changeText = function(){
scope.text = 'New directive text';
};
},
template: '<h2>{{text}}</h2>'
};
});
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<h1>{{text}}</h1>
<my-dir text="dirText"></my-dir>
<button ng-click="click()">Change Directive Text</button>
</div>
</div>
在尝试了$broadcast
和control
对象解决方案之后,我实际上建议尝试绑定值或数组。control
对象是实现所需结果的简单方法,但在我的测试中非常难以发现且容易出错。
此代码笔构建了 BernardV 的示例,但使用消息数组作为非常明显的控件绑定。如果需要,您也可以轻松地$watch
指令中的消息数组。核心思想是在指令中使用:
scope: { messages: "=", room: "@" },
从控制器(具有"房间"数组)中,您将执行以下操作:
$scope.addMessages = function () {
angular.forEach($scope.rooms, function(room, index) {
room.messages.push("A new message! # " + (index+1);
})
}
独立的指令,独立的消息和高度可发现的。当然,您可以在指令中只显示最新消息,或者简单地绑定字符串而不是数组。这个解决方案至少对我们来说效果更好。
- 显示指令时调用指令方法
- AngularJS:如何调用指令中定义的函数'控制器的作用域
- 如何在ngRepeat中调用指令
- 未对输入更改调用指令
- 从子指令调用指令函数不起作用
- 从 AngularJS 中的父控制器调用指令的方法
- 从服务 AngularJS + TypeScript 调用指令
- 如何从 Angular 上的控制器调用指令的函数
- 如何从 JavaScript 调用指令函数
- Angular JS 如何从指令模板内容事件调用指令范围函数
- 从控制器调用指令中函数的最佳方法是什么
- 从传入的内容调用指令方法
- Angularjs-在ng-init函数完成后调用指令
- 从另一个指令调用指令
- 从父指令角度调用指令函数
- 如何从控制器调用指令作用域上的函数
- 有棱角的从html调用指令中的函数
- 动态元素未在AngularJS上调用指令方法
- 是'不良做法'用于Angular控制器调用指令上的函数
- AngularJS:从具有隔离作用域的控制器中调用指令中的函数