mcb*_*jam 294 angularjs angularjs-directive
我有一个指令,这里是代码:
.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
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);
}
}
})
Run Code Online (Sandbox Code Playgroud)
我想呼吁updateMap()
用户采取行动.操作按钮不在指令上.
updateMap()
从控制器呼叫的最佳方式是什么?
Oli*_*and 364
如果要使用隔离范围,可以使用=
控制器范围中变量的双向绑定来传递控制对象.您还可以在具有相同控件对象的页面上控制同一指令的多个实例.
angular.module('directiveControlDemo', [])
.controller('MainCtrl', function($scope) {
$scope.focusinControl = {};
})
.directive('focusin', function factory() {
return {
restrict: 'E',
replace: true,
template: '<div>A:{{internalControl}}</div>',
scope: {
control: '='
},
link: function(scope, element, attrs) {
scope.internalControl = scope.control || {};
scope.internalControl.takenTablets = 0;
scope.internalControl.takeTablet = function() {
scope.internalControl.takenTablets += 1;
}
}
};
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="directiveControlDemo">
<div ng-controller="MainCtrl">
<button ng-click="focusinControl.takeTablet()">Call directive function</button>
<p>
<b>In controller scope:</b>
{{focusinControl}}
</p>
<p>
<b>In directive scope:</b>
<focusin control="focusinControl"></focusin>
</p>
<p>
<b>Without control object:</b>
<focusin></focusin>
</p>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
Mar*_*cok 71
假设动作按钮使用相同的控制器$scope
的指令,只是定义功能updateMap
上$scope
的链接功能里面.然后,您的控制器可以在单击操作按钮时调用该功能.
<div ng-controller="MyCtrl">
<map></map>
<button ng-click="updateMap()">call updateMap()</button>
</div>
Run Code Online (Sandbox Code Playgroud)
app.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
$scope.updateMap = function() {
alert('inside updateMap()');
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
根据@ FlorianF的评论,如果指令使用隔离范围,事情会更复杂.这是使其工作的一种方法:set-fn
向map
指令添加一个属性,该指令将向控制器注册指令函数:
<map set-fn="setDirectiveFn(theDirFn)"></map>
<button ng-click="directiveFn()">call directive function</button>
Run Code Online (Sandbox Code Playgroud)
scope: { setFn: '&' },
link: function(scope, element, attrs) {
scope.updateMap = function() {
alert('inside updateMap()');
}
scope.setFn({theDirFn: scope.updateMap});
}
Run Code Online (Sandbox Code Playgroud)
function MyCtrl($scope) {
$scope.setDirectiveFn = function(directiveFn) {
$scope.directiveFn = directiveFn;
};
}
Run Code Online (Sandbox Code Playgroud)
Alw*_*ing 34
虽然在指令的隔离范围上公开一个对象以便于与它进行通信可能很诱人,但这样做可能会导致混乱的"意大利面条"代码,特别是如果你需要通过几个层次链接这种通信(控制器,指令,嵌套指令等)
我们最初沿着这条路走下去但是经过一些研究后发现它更有意义并且导致更易于维护和可读的代码暴露事件和属性,指令将通过服务用于通信,然后在该服务的属性中使用$ watch指令或任何其他需要对这些通信变更作出反应的控制.
这种抽象与AngularJS的依赖注入框架非常吻合,因为您可以将服务注入需要对这些事件做出反应的任何项目.如果查看Angular.js文件,您会看到其中的指令也以这种方式使用services和$ watch,它们不会在隔离范围上公开事件.
最后,如果您需要在彼此依赖的指令之间进行通信,我建议在这些指令之间共享一个控制器作为通信方式.
AngularJS的最佳实践Wiki也提到了这一点:
仅对原子事件使用.$ broadcast(),. $ emit()和.$ on()在整个应用程序中全局相关的事件(例如用户身份验证或应用程序关闭).如果您需要特定于模块,服务或小部件的事件,则应考虑服务,指令控制器或第三方库
- $ scope.$ watch()应该取代事件的需要
- 直接注入服务和调用方法对于直接通信也很有用
- 指令能够通过指令控制器直接相互通信
Che*_*aks 15
基于Oliver的回答 - 您可能并不总是需要访问指令的内部方法,在这些情况下,您可能不希望创建空白对象并向control
指令添加attr以防止它抛出错误(cannot set property 'takeTablet' of undefined
).
您还可能希望在指令中的其他位置使用该方法.
我会添加一个检查以确保scope.control
存在,并以与显示模块模式类似的方式设置方法
app.directive('focusin', function factory() {
return {
restrict: 'E',
replace: true,
template: '<div>A:{{control}}</div>',
scope: {
control: '='
},
link : function (scope, element, attrs) {
var takenTablets = 0;
var takeTablet = function() {
takenTablets += 1;
}
if (scope.control) {
scope.control = {
takeTablet: takeTablet
};
}
}
};
});
Run Code Online (Sandbox Code Playgroud)
Mud*_*Ali 12
说实话,我对这个帖子中的任何答案都不太相信.那么,这是我的解决方案:
该方法与指令$scope
是共享指令还是孤立指令无关
A factory
注册指令实例
angular.module('myModule').factory('MyDirectiveHandler', function() {
var instance_map = {};
var service = {
registerDirective: registerDirective,
getDirective: getDirective,
deregisterDirective: deregisterDirective
};
return service;
function registerDirective(name, ctrl) {
instance_map[name] = ctrl;
}
function getDirective(name) {
return instance_map[name];
}
function deregisterDirective(name) {
instance_map[name] = null;
}
});
Run Code Online (Sandbox Code Playgroud)
指令代码,我通常把所有不处理DOM的逻辑放在指令控制器中.并在我们的处理程序中注册控制器实例
angular.module('myModule').directive('myDirective', function(MyDirectiveHandler) {
var directive = {
link: link,
controller: controller
};
return directive;
function link() {
//link fn code
}
function controller($scope, $attrs) {
var name = $attrs.name;
this.updateMap = function() {
//some code
};
MyDirectiveHandler.registerDirective(name, this);
$scope.$on('destroy', function() {
MyDirectiveHandler.deregisterDirective(name);
});
}
})
Run Code Online (Sandbox Code Playgroud)
模板代码
<div my-directive name="foo"></div>
Run Code Online (Sandbox Code Playgroud)
使用factory
&运行公开的方法访问控制器实例
angular.module('myModule').controller('MyController', function(MyDirectiveHandler, $scope) {
$scope.someFn = function() {
MyDirectiveHandler.get('foo').updateMap();
};
});
Run Code Online (Sandbox Code Playgroud)
从棱角分明的书中拿出一片关于它们如何处理的叶子
<form name="my_form"></form>
Run Code Online (Sandbox Code Playgroud)
使用$ parse并在$parent
范围上注册控制器.此技术不适用于隔离$scope
指令.
angular.module('myModule').directive('myDirective', function($parse) {
var directive = {
link: link,
controller: controller,
scope: true
};
return directive;
function link() {
//link fn code
}
function controller($scope, $attrs) {
$parse($attrs.name).assign($scope.$parent, this);
this.updateMap = function() {
//some code
};
}
})
Run Code Online (Sandbox Code Playgroud)
使用在控制器内访问它 $scope.foo
angular.module('myModule').controller('MyController', function($scope) {
$scope.someFn = function() {
$scope.foo.updateMap();
};
});
Run Code Online (Sandbox Code Playgroud)
Axd*_*der 10
有点晚了,但这是一个带有隔离范围和"事件"的解决方案,用于调用指令中的函数.此解决方案的灵感来自satchmorun的SO帖子,并添加了一个模块和一个API.
//Create module
var MapModule = angular.module('MapModule', []);
//Load dependency dynamically
angular.module('app').requires.push('MapModule');
Run Code Online (Sandbox Code Playgroud)
创建API以与指令通信.addUpdateEvent将事件添加到事件数组,updateMap调用每个事件函数.
MapModule.factory('MapApi', function () {
return {
events: [],
addUpdateEvent: function (func) {
this.events.push(func);
},
updateMap: function () {
this.events.forEach(function (func) {
func.call();
});
}
}
});
Run Code Online (Sandbox Code Playgroud)
(也许你必须添加删除事件的功能.)
在指令中设置对MapAPI的引用,并在调用MapApi.updateMap时将$ scope.updateMap添加为事件.
app.directive('map', function () {
return {
restrict: 'E',
scope: {},
templateUrl: '....',
controller: function ($scope, $http, $attrs, MapApi) {
$scope.api = MapApi;
$scope.updateMap = function () {
//Update the map
};
//Add event
$scope.api.addUpdateEvent($scope.updateMap);
}
}
});
Run Code Online (Sandbox Code Playgroud)
在"main"控制器中添加对MapApi的引用,只需调用MapApi.updateMap()来更新映射.
app.controller('mainController', function ($scope, MapApi) {
$scope.updateMapButtonClick = function() {
MapApi.updateMap();
};
}
Run Code Online (Sandbox Code Playgroud)
您可以指定一个DOM属性,该属性可用于允许指令在父作用域上定义函数.然后,父作用域可以像任何其他方法一样调用此方法. 这是一个吸烟者.以下是相关代码.
clearfn
是指令元素的一个属性,父作用域可以将一个scope属性传递到该属性,然后该指令可以设置为一个完成所需行为的函数.
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<style>
my-box{
display:block;
border:solid 1px #aaa;
min-width:50px;
min-height:50px;
padding:.5em;
margin:1em;
outline:0px;
box-shadow:inset 0px 0px .4em #aaa;
}
</style>
</head>
<body ng-controller="mycontroller">
<h1>Call method on directive</h1>
<button ng-click="clear()">Clear</button>
<my-box clearfn="clear" contentEditable=true></my-box>
<script>
var app = angular.module('myapp', []);
app.controller('mycontroller', function($scope){
});
app.directive('myBox', function(){
return {
restrict: 'E',
scope: {
clearFn: '=clearfn'
},
template: '',
link: function(scope, element, attrs){
element.html('Hello World!');
scope.clearFn = function(){
element.html('');
};
}
}
});
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
317628 次 |
最近记录: |