我已经在这个问题上工作了两天了。我觉得它应该更简单。
我想创建一个使用如下的指令:
<my-directive ng-something="something">
content
</my-directive>
并输出:
<my-directive ng-something="something" ng-more="more">
content
</my-directive>
当然它会有一个链接功能和控制器做一些工作,但主要关注点是:
例如,假设我想创建一个在内部执行某些操作的元素:
<click-count ng-repeat="X in ['A', 'B', 'C']"> {{ X }} </click-count>
可以编译成这样的东西:
<click-count ng-click="internalFn()"> A </click-count>
<click-count ng-click="internalFn()"> B </click-count>
<click-count ng-click="internalFn()"> C </click-count>
其中internalFn
将在clickCount
指令的内部范围中定义。
我的一次尝试就是这个Plunker:http://plnkr.co/edit/j9sUUS?p=preview
由于Plunker似乎失败了,这是代码:
angular.module('app', []).directive('clickCount', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
ccModel: '='
},
compile: function(dElement) {
dElement.attr("ngClick", "ccModel = ccModel + 1");
return function postLink($scope, iElement, iAttrs, controller, transclude) {
transclude(function(cloned) { iElement.append(cloned); });
};
},
controller: function ($scope) {
$scope.ccModel = 0;
}
};
});
这是使用指令的一些HTML:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app">
<hr> The internal 'ng-click' doesn't work:
<click-count ng-repeat="X in ['A', 'B', 'C']" cc-model="counter">
{{ X }}, {{ counter }}
</click-count>
<hr> But an external 'ng-click' does work:
<click-count ng-repeat="X in ['A', 'B', 'C']" cc-model="bla" ng-init="counter = 0" ng-click="counter = counter + 1">
{{ X }}, {{ counter }}
</click-count>
<hr>
</body>
</html>
因为元素保持其名称,所以可以按如下方式使用css:
click-count {
display: block;
border: solid 1px;
background-color: lightgreen;
font-weight: bold;
margin: 5px;
padding: 5px;
}
我对它可能出现的问题有几点看法,但我尝试了许多替代方法。如果我在链接器中乱七八糟,也许再次尝试$compile
,控制器函数也必须被调用两次。无论如何,我们非常感谢如何正确地做到这一点。
答案 0 :(得分:1)
正如我所理解的那样,您正在尝试修改DOM元素并使用属性添加一些指令。这意味着您的指令应该在所有其他指令运行之前运行。为了控制指令,执行顺序Angular提供priority
属性。大多数指令都以优先级0
运行,这意味着如果您的指令具有更高的优先级,它将在之前运行。但遗憾的是,ngRepeat
不仅具有优先级1000
,还具有terminal:true
定义,这意味着一旦元素具有ngRepeat
,您就无法在相同的元素指令上指定更高优先级ngRepeat
优先。您可以添加属性和行为,但不能添加应在ngClick
之前运行的指令。但是angular.module('app', []).directive('clickCount', function() {
return {
restrict: 'E',
replace: true,
compile: function(tElement) {
return {
pre: function(scope, iElement) {
iElement.attr('ng-click', 'counter = counter +1'); // <- Add attribute
},
post: function(scope, iElement) {
iElement.on('click', function() { // <- Add behavior
scope.$apply(function(){ // <- Since scope variables may be modified, don't forget to apply the scope changes
scope.$eval(iElement.attr('ng-click')); // <- Evaluate expression defined in ng-click attribute in context of scope
});
});
}
}
}
};
});
有一种解决方法:
ngRepeat
JSBin:http://jsbin.com/sehobavo/1/edit
另一种解决方法是在没有angular.module('app', []).directive('clickCount', function($compile) {
return {
restrict: 'E',
replace: true,
compile: function(tElement) {
return {
pre: function(scope, iElement) {
if(iElement.attr('ng-repeat')) { // <- Avoid recursion
iElement.attr('ng-click', 'counter = counter +1'); // <- Add custom attributes and directives
iElement.removeAttr('ng-repeat'); // <- Avoid recursion
$compile(iElement)(scope); // <- Recompile your element to make other directives work
}
}
}
}
};
});
的情况下重新编译您的指令:
{{1}}