博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何调用AngularJS指令中定义的方法?
阅读量:2289 次
发布时间:2019-05-09

本文共 8189 字,大约阅读时间需要 27 分钟。

本文翻译自:

I have a directive, here is the code : 我有一个指令,这里是代码:

.directive('map', function() {    return {        restrict: 'E',        replace: true,        template: '
', link: function($scope, element, attrs) { var center = new google.maps.LatLng(50.1, 14.4); $scope.map_options = { zoom: 14, center: center, mapTypeId: google.maps.MapTypeId.ROADMAP }; // create map var map = new google.maps.Map(document.getElementById(attrs.id), $scope.map_options); var dirService= new google.maps.DirectionsService(); var dirRenderer= new google.maps.DirectionsRenderer() var showDirections = function(dirResult, dirStatus) { if (dirStatus != google.maps.DirectionsStatus.OK) { alert('Directions failed: ' + dirStatus); return; } // Show directions dirRenderer.setMap(map); //$scope.dirRenderer.setPanel(Demo.dirContainer); dirRenderer.setDirections(dirResult); }; // Watch var updateMap = function(){ dirService.route($scope.dirRequest, showDirections); }; $scope.$watch('dirRequest.origin', updateMap); google.maps.event.addListener(map, 'zoom_changed', function() { $scope.map_options.zoom = map.getZoom(); }); dirService.route($scope.dirRequest, showDirections); } }})

I would like to call updateMap() on a user action. 我想在用户操作上调用updateMap() The action button is not on the directive. 操作按钮不在指令上。

What is the best way to call updateMap() from a controller? 从控制器调用updateMap()的最佳方法是什么?


#1楼

参考:


#2楼

Assuming that the action button uses the same controller $scope as the directive, just define function updateMap on $scope inside the link function. 假设操作按钮使用与指令相同的控制器$scope ,只需在链接函数内的$scope上定义函数updateMap Your controller can then call that function when the action button is clicked. 然后,您的控制器可以在单击操作按钮时调用该功能。

app.directive('map', function() {    return {        restrict: 'E',        replace: true,        template: '
', link: function($scope, element, attrs) { $scope.updateMap = function() { alert('inside updateMap()'); } } }});


As per @FlorianF's comment, if the directive uses an isolated scope, things are more complicated. 根据@ FlorianF的评论,如果指令使用隔离范围,事情会更复杂。 Here's one way to make it work: add a set-fn attribute to the map directive which will register the directive function with the controller: 以下是使其工作的一种方法:向map指令添加set-fn属性,该指令将向控制器注册指令函数:

scope: { setFn: '&' },link: function(scope, element, attrs) {    scope.updateMap = function() {       alert('inside updateMap()');    }    scope.setFn({theDirFn: scope.updateMap});}
function MyCtrl($scope) {    $scope.setDirectiveFn = function(directiveFn) {        $scope.directiveFn = directiveFn;    };}


#3楼

If you want to use isolated scopes you can pass a control object using bi-directional binding = of a variable from the controller scope. 如果要使用隔离作用域可以传递使用双向结合的控制对象=来自控制器范围的可变的。 You can also control also several instances of the same directive on a page with the same control object. 您还可以在具有相同控件对象的页面上控制同一指令的多个实例。

angular.module('directiveControlDemo', []) .controller('MainCtrl', function($scope) { $scope.focusinControl = {}; }) .directive('focusin', function factory() { return { restrict: 'E', replace: true, template: '
A:{
{internalControl}}
', scope: { control: '=' }, link: function(scope, element, attrs) { scope.internalControl = scope.control || {}; scope.internalControl.takenTablets = 0; scope.internalControl.takeTablet = function() { scope.internalControl.takenTablets += 1; } } }; });
 

In controller scope: {

{focusinControl}}

In directive scope:

Without control object:


#4楼

Building on Oliver's answer - you might not always need to access a directive's inner methods, and in those cases you probably don't want to have to create a blank object and add a control attr to the directive just to prevent it from throwing an error ( cannot set property 'takeTablet' of undefined ). 基于Oliver的回答 - 您可能并不总是需要访问指令的内部方法,在这些情况下,您可能不希望创建空白对象并向control指令添加control attr以防止它引发错误( cannot set property 'takeTablet' of undefined )。

You also might want to use the method in other places within the directive. 您还可能希望在指令中的其他位置使用该方法。

I would add a check to make sure scope.control exists, and set methods to it in a similar fashion to the revealing module pattern 我会添加一个检查以确保scope.control存在,并以与显示模块模式类似的方式设置方法

app.directive('focusin', function factory() {  return {    restrict: 'E',    replace: true,    template: '
A:{
{control}}
', scope: { control: '=' }, link : function (scope, element, attrs) { var takenTablets = 0; var takeTablet = function() { takenTablets += 1; } if (scope.control) { scope.control = { takeTablet: takeTablet }; } } };});

#5楼

You can specify a DOM attribute that can be used to allow the directive to define a function on the parent scope. 您可以指定一个DOM属性,该属性可用于允许指令在父作用域上定义函数。 The parent scope can then call this method like any other. 然后,父作用域可以像任何其他方法一样调用此方法。 a plunker. 一个吸烟者。 And below is the relevant code. 以下是相关代码。

clearfn is an attribute on the directive element into which the parent scope can pass a scope property which the directive can then set to a function that accomplish's the desired behavior. clearfn是指令元素的一个属性,父作用域可以将一个scope属性传递到该属性,然后该指令可以设置为一个完成所需行为的函数。

          

Call method on directive


#6楼

Although it might be tempting to expose an object on the isolated scope of a directive to facilitate communicating with it, doing can lead to confusing "spaghetti" code, especially if you need to chain this communication through a couple levels (controller, to directive, to nested directive, etc.) 虽然在指令的隔离范围上公开一个对象以便于与它进行通信可能很诱人,但这样做可能会导致混乱的“意大利面条”代码,特别是如果你需要通过几个层次链接这个通信(控制器,指令,嵌套指令等)

We originally went down this path but after some more research found that it made more sense and resulted in both more maintainable and readable code to expose events and properties that a directive will use for communication via a service then using $watch on that service's properties in the directive or any other controls that would need to react to those changes for communication. 我们最初走的是这条路,但是经过一些研究后发现它更有意义,并且导致更易于维护和可读的代码暴露事件和属性,指令将通过服务用于通信,然后在该服务的属性中使用$ watch指令或任何其他需要对这些通信变更作出反应的控制。

This abstraction works very nicely with AngularJS's dependency injection framework as you can inject the service into any items that need to react to those events. 这种抽象与AngularJS的依赖注入框架非常吻合,因为您可以将服务注入需要对这些事件做出反应的任何项目。 If you look at the Angular.js file, you'll see that the directives in there also use services and $watch in this manner, they don't expose events over the isolated scope. 如果查看Angular.js文件,您会看到其中的指令也以这种方式使用services和$ watch,它们不会在隔离范围上公开事件。

Lastly, in the case that you need to communicate between directives that are dependent on one another, I would recommend sharing a controller between those directives as the means of communication. 最后,如果您需要在彼此依赖的指令之间进行通信,我建议在这些指令之间共享一个控制器作为通信手段。

also mentions this: 也提到了这一点:

Only use .$broadcast(), .$emit() and .$on() for atomic events Events that are relevant globally across the entire app (such as a user authenticating or the app closing). 仅对原子事件使用。$ broadcast(),. $ emit()和。$ on()在整个应用程序中全局相关的事件(例如用户身份验证或应用程序关闭)。 If you want events specific to modules, services or widgets you should consider Services, Directive Controllers, or 3rd Party Libs 如果您需要特定于模块,服务或小部件的事件,则应考虑服务,指令控制器或第三方库

  • $scope.$watch() should replace the need for events $ scope。$ watch()应该取代事件的需要
  • Injecting services and calling methods directly is also useful for direct communication 直接注入服务和调用方法对于直接通信也很有用
  • Directives are able to directly communicate with each other through directive-controllers 指令能够通过指令控制器直接相互通信

转载地址:http://owjnb.baihongyu.com/

你可能感兴趣的文章