我如何可以公开从指令的方法? 我知道,我应该使用的属性数据,但我真的想揭露的行为 ,而不是数据 。 东西父控制器可以调用。
比方说,我的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
是指对儿童的范围和不会轻易提供给家长。
在我来说,我认为污染父范围是一个坏主意,我真的想避免它。
所以,我怎么可以公开从指令父控制器的功能? 或者:我怎样才能调用从父控制器指令的方法?
Answer 1:
可以用分离的范围由设置在这绑定到控制器双向范围的变量(使用“=”)执行此操作。 在你的指令,你可以在函数然后分配给该变量,角将使用绑定找到您的控制器对应的变量。 该变量将指向您的控制器可以调用一个函数。
http://jsfiddle.net/GWCCr/
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");
}
}
};
});
Answer 2:
而不是试图找出如何调用隐藏的指令,我觉得里面的函数,你应该问自己: 为什么我要调用的指令定义的功能?
其中一个原因,我能想到的是:触发也可以通过应用程序的用户从指令中触发该指令的一些行为 。
如果是这样,显然和Angulary的事情将播出包含应该对其做出反应的指令一个范围的事件 。 然后,该指令会听取该事件,并通过自身触发其功能。
这有额外的好处:
- 您可以在事件数据对象发送参数,如果你想
- (如果它们形成集合例如),您可以触发多个指令的反应
- 可以用一个指令,该指令是在该范围层次深通信(例如,如果该指令是另一指令,是其他指令的内部,等等内),而不传递函数回调通过每个嵌套指令
- 它不会破坏该指令的隔离
例
让我们试着想出了一个很简单的例子:假设我们有一个显示从某处下载随机励志报价的Widget。 它也有一个按钮,涨跌幅为不同的一种。
下面是该指令的模板:
<p>{{ quote }}</p>
<button ng-click="refreshQuote()"></button>
而这里的指令的代码:
app.directive("randomQuote", function () {
return {
restrict: "E",
scope: {},
link: function (scope) {
scope.refreshQuote = function () {
scope.quote = ... // some complicated code here
};
scope.refreshQuote();
}
};
});
请注意,该指令是完全独立的:它有一个分离的范围和它本身并不报价取。
让我们假设,我们也希望能够从控制器刷新报价。 这可能是因为在控制器代码中调用这个简单:
$scope.$broadcast("refresh-random-quote");
要添加事件处理程序,我们必须将此代码添加到link
指令的功能:
scope.$on("refresh-random-quote", function () {
scope.refreshQuote();
});
通过这种方式,我们创建了从控制器到该指令的单向通信信道不破该指令的隔离,同时工作,如果该指令代码的范围层次广播事件嵌套深。
Answer 3:
我怎样才能从暴露指令父控制器的功能?
或者:我怎样才能调用从父控制器指令的方法?
嗯,我不认为你应该尝试做到这一点(即耦合控制器行为的指令),但如果你必须...这里有一个方法可以做到这一点:通过一个控制器功能到你的指令,其中,指令可以打电话通知指示功能的控制器:
<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});
}
};
});
小提琴
Answer 4:
为了contribuite,@georgeawg给我用服务做的工作凉爽的解决方案。 这样,您就可以处理同一个页面上的多个指令。
<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>
Answer 5:
AngularJS V1.7.1的版本*引入了新的NG-REF指令 。
的NG-REF属性告诉AngularJS发布一个组件的控制器上的当前范围。 这对于具有一个成分是有用的,诸如音频播放器暴露其API来同级组件。 它的播放和停止控件可以很容易地访问。
欲了解更多信息,请参阅
- AngularJS
ng-ref
指令API参考 - 新AngularJS NG-REF指令的陷阱 。
文章来源: How to expose behavior from a directive with isolated scope?