I've been grappling with this problem for the past two days. It seems like it should have a simpler solution.
Issue Description
The objective is to develop a directive that can be used in the following manner:
<my-directive ng-something="something">
content
</my-directive>
The desired output should look like this:
<my-directive ng-something="something" ng-more="more">
content
</my-directive>
Although it will involve a linking function and controller that perform certain tasks, the key considerations are:
- ensuring that the DOM element retains its original name for intuitive CSS styling,
- ensuring that existing attribute directives continue to function correctly, and
- allowing the addition of new attribute directives by the element directive itself.
Example Scenario
For instance, if we want to create an element that responds internally when clicked:
<click-count ng-repeat="X in ['A', 'B', 'C']"> {{ X }} </click-count>
This may translate into something similar to:
<click-count ng-click="internalFn()"> A </click-count>
<click-count ng-click="internalFn()"> B </click-count>
<click-count ng-click="internalFn()"> C </click-count>
Where internalFn
would be defined within the internal scope of the clickCount
directive.
Initial Attempt
One approach I tried out can be viewed on Plunker at: http://plnkr.co/edit/j9sUUS?p=preview
When Plunker is inaccessible, here's the code snippet:
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;
}
};
});
Here's some HTML utilizing the directive:
<!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' isn't functioning:
<click-count ng-repeat="X in ['A', 'B', 'C']" cc-model="counter">
{{ X }}, {{ counter }}
</click-count>
<hr> However, 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>
Furthermore, retaining the element name enables the usage of CSS as follows:
click-count {
display: block;
border: solid 1px;
background-color: lightgreen;
font-weight: bold;
margin: 5px;
padding: 5px;
}
I have contemplated several potential issues with the current implementation and have experimented with various alternative strategies. If there are any insights or examples demonstrating the correct approach, they would be greatly appreciated.