我目前正在开发一个简单的模块,以屏幕右下角出现的祝酒词或弹出窗口的形式向用户显示通知。以下指令很有效,除了我更喜欢
a)使用.bind
代替ng-click
来处理手动驳回通知;
b)使用replace: true
帮助减少一些生成的标记
toast.directive('toast', function() {
return {
link: function($scope, $element, $attrs, $location) {
$scope.delayDismiss = function(index) {
setTimeout(function() {
$scope.dismiss(index);
$scope.$apply();
}, 5000);
}
$scope.dismiss = function(index) {
$scope.messages[index].dismissed = true;
}
$element.bind('click', function() {
console.log('This never triggers');
});
},
replace: true,
restrict: 'E',
template: '<li ng-repeat="toast in messages" ng-click="dismiss($index)" ng-init="delayDismiss($index)" ng-if="!toast.dismissed">{{toast.sender}} says {{toast.message}}</li>'
}
});
问题是,现在,$element
函数中的link()
引用生成的Angular注释而不是<li>
,导致绑定的click事件永远不会触发。这对我没有任何意义。
我是否误解了整个指令?
答案 0 :(得分:2)
a)使用.bind而不是ng-click处理手动解除通知;
从指令的模板中删除ngRepeat
,您应该可以在指令的link
函数中执行此操作。但是,我建议不要这样做,如果这只是您的偏好问题。
有关原因的详细信息,请参阅How do I “think in AngularJS” if I have a jQuery background?的答案。
您对ngRepeat
的使用导致链接元素引用生成的评论节点而不是<li>
。
将ngRepeat
指令移到指令模板之外,行为更接近您的期望:
<toast ng-repeat="toast in messages"></toast>
b)使用replace:true help减少一些生成的标记
这很好,但请注意角度1.3文档提到replace
has been deprecated并将从下一个主要版本中删除。
为了使指令更加可重复使用&#34;,我会将个人toast
的逻辑移到自己的工厂,而不是试图在link
函数上处理它指令。
我还会在模板<li>
和transclude: true
中为指令的定义添加ngTransclude
。
查看强>
<ol>
<toast ng-repeat="toast in messages">
{{toast.sender}} says {{toast.message}}
</toast>
</ol>
<强>控制器强>
controller("MainCtrl", function ($scope, $toast) {
$scope.addToast = function(message, sender, timeout) {
$toast.add(message, sender, parseInt(timeout));
};
})
<强>指令强>
directive('toast', function() {
return {
replace: true,
restrict: 'E',
template: '<li ng-click="toast.dismiss()" ng-transclude></li>',
transclude: true
}
})
<强>工厂强>
factory("$toast", function($rootScope, $timeout) {
var messages = $rootScope.messages = [];
var $toast = (function() {
function $toast(message, sender, timeout) {
var self = this;
this.message = message;
this.sender = sender;
this.timeout = timeout || $toast.defaultTimeout;
this.timer = $timeout(function() {
self.dismiss();
}, this.timeout);
}
$toast.prototype.dismiss = function() {
if (this.timer) {
$timeout.cancel(this.timer);
this.timer = null;
}
var index = messages.indexOf(this);
if (index !== -1) {
messages.splice(index, 1);
}
};
return $toast;
})();
$toast.defaultTimeout = 5000;
$toast.add = function(message, sender, timeout) {
messages.push(new $toast(message, sender, timeout));
return $toast;
};
return $toast;
})
以下是一个工作示例:http://plnkr.co/edit/52JiHWi2jgloIyDst74I?p=preview