如何从指令中公开方法?我知道我应该使用数据属性,但我真的想公开行为,而不是数据。父控制器可以调用的东西。
假设我的DOM看起来像:
<div ng-app="main">
<div ng-controller="MyCtrl">
<button ng-click="call()" >Call</button>
<div id="container" my-directive> </div>
</div>
</div>
JavaScript的:
angular.module("main", []).controller("MyCtrl", function($scope) {
$scope.call = function() {
$scope.myfn();
};
}).directive("myDirective", function() {
return {
// scope: {},
controller: function($scope) {
$scope.myfn = function() {
console.log("myfn called");
}
}
};
});
jsFiddle:http://jsfiddle.net/5gDjQ/7/
如果scope
被注释掉(即指令没有隔离范围),它就可以了。当我按下按钮时,会调用myfn
并登录到控制台。
一旦我取消注释scope
,它就无效。 myfn
是在子范围上定义的,父母不容易获得。
在我的情况下,我认为污染父范围是一个坏主意,我真的想避免它。
那么,我如何将一个函数从指令公开给父控制器?或者:如何从父控制器调用指令上的方法?
答案 0 :(得分:26)
您可以通过在与控制器双向绑定的范围中设置变量(使用“=”)来使用隔离范围执行此操作。在您的指令中,您可以将该函数分配给该变量,而angular将使用该绑定在您的控制器中查找相应的变量。该变量将指向控制器可以调用的函数。
html:注意新的attrib:
<div ng-app="main">
<div ng-controller="MyCtrl">
<button ng-click="call()" >Call</button>
<div id="container" my-directive my-fn="fnInCtrl"> </div>
</div>
</div>
JS:
angular.module("main", []).controller("MyCtrl", function($scope) {
$scope.call = function() {
$scope.fnInCtrl();
};
}).directive("myDirective", function() {
return {
scope: {
myFn: '='
},
controller: function($scope) {
$scope.myFn = function() {
console.log("myfn called");
}
}
};
});
答案 1 :(得分:7)
如何将指令中的函数公开给父控制器?
或者:如何从父控制器调用指令上的方法?
好吧,我认为你不应该尝试这样做(即将控制器行为耦合到指令),但是如果你必须......这是你可以做到的一种方法:将控制器函数传递给你的指令,该指令可以调用以通知控制器指令函数:
<div id="container" my-directive cb="setDirectiveFn(fn)"></div>
directive("myDirective", function() {
return {
scope: { cb: '&' },
controller: function($scope) {
$scope.myfn = function() {
console.log("myfn called");
}
$scope.cb({fn: $scope.myfn});
}
};
});
答案 2 :(得分:1)
为了贡献,@ georgeawg给了我一个很酷的解决方案,使用Service来完成这项工作。这样您就可以在同一页面上处理多个指令。
<html ng-app="myApp">
<head>
<script src="https://opensource.keycdn.com/angularjs/1.6.5/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
<h1>^v1.6.0 ($postLink hook required)</h1>
<my-directive name="sample1" number="number1"></my-directive>
<my-directive name="sample2" number="number2"></my-directive>
</body>
<script>
angular.module('myApp', [])
.controller('mainCtrl', ['$scope', 'myDirectiveFactory', function ($scope, myDirectiveFactory) {
$scope.number1 = 10
$scope.number2 = 0
this.$postLink = function () {
myDirectiveFactory.get('sample2')
.increment()
.increment()
.increment()
.increment()
myDirectiveFactory.get('sample1')
.increment()
.increment()
myDirectiveFactory.get('sample2')
.decrement()
}
}])
.factory('myDirectiveFactory', function () {
var instance = {}
return {
get: function (name) {
return instance[name]
},
register: function (name, value) {
return instance[name] = value
},
destroy: function (name) {
delete instance[name]
}
}
})
.controller('myDirectiveCtrl', ['$scope', 'myDirectiveFactory', function ($scope, myDirectiveFactory) {
$scope.name = $scope.name || 'myDirective'
$scope.$on('$destroy', function () {
myDirectiveFactory.destroy($scope.name)
})
var service = {
increment: function () {
$scope.number++
return this
},
decrement: function () {
$scope.number--
return this
}
}
myDirectiveFactory.register($scope.name, service)
}])
.directive('myDirective', [function () {
return {
controller: 'myDirectiveCtrl',
restrict: 'E',
scope: {
number: '<',
name: '@?'
},
template: '<p> {{ number }} </p>'
}
}])
</script>
</html>
答案 3 :(得分:0)
AngularJS V1.7.1的发布 * 引入了新的ng-ref directive。
ng-ref属性告诉AngularJS在当前作用域上发布组件的控制器。这对于使诸如音频播放器之类的组件将其API暴露给同级组件很有用。可以轻松访问其播放和停止控件。
有关更多信息,请参见