Reputation: 259
I am Angular newbie and I am struggling with what I think to be a standard problem.
What I am trying to implement is a custom directive called "clicker" that is meant to be included in "ul ng-repeat" html elements.
Here is an example of how I imagine my HTML to be:
<ul ng-repeat="item in items">
<clicker>{{item}}</clicker>
...
</ul>
To accomplish that I created a custom directive "clicker" here is how it looks like:
myModule.directive('clicker', function() {
return {
restrict : 'E',
replace : true,
transclude: true,
scope : true,
template : '<li><a ng-click="showMeClicked()" ng-transclude></a></li>',
controller: function($scope, $element, $document){
var test = {}; //In debug $scope, $element, $document are injected here!
$scope.showMeClicked = function ($scope, $element, $document) {
//In debug all $scope, $element, $document are undefined here!
//This line works and deletes all class properties of my <li> along with id properties of their
//child <a> element. Since $element is undefined this code was the only way I manage to do that action.
angular.element(document.querySelectorAll('.button_selected')).removeClass('button_selected').children().removeAttr('id');
//This code does not work since $element is undefined!
$element.addClass('button_selected');
$element.children().prop('id', 'button_selected_font');
//My expected result is:
//'<li class="button_selected">'
// '<a id="button_selected_font" ng-click="showMeClicked()" ng-transclude></a>'
//'</li>'
};
}
};
});
What I want to do is make my "clicker" elements clickable and on clicking them I want to change their appearance on the screen. Basically what I need is the $element to be properly injected to my showMeClicked function so I can use it to set my list's "class" and my anchor's "id". I tried to give good comments in my example code.
I tried to use link function instead of controller one, but the current element is not injected there too. The scope : true property that I have given to my directive is just for the example it may be changed if needed.
I am trying to avoid using jQuery and use the Angular's jqLite.
Do anyone have any suggestion?
Thanks in advance!
EDIT: At the moment I am not using the ng-repeat directive on my "ul". Instead I manually declared 9 "clicker" tags. As a result in my resulting HTML the tags are replaced with the proper code from the directive and I see a list of "li"s. You can see my "ul" content here: pastebin.com/JPFqcnSU
As I click on any of the links it results in the expected exception:
Cannot access addClass for undefined.
Upvotes: 2
Views: 2579
Reputation: 16368
You need to access your current element by passing an index:
$element[0].style...
var app = angular.module('myApp',[]);
function MyController(){
var vm = this;
this.items = ["a","b","c","d","e"];
}
app.controller('MyController',[MyController])
.directive('clicker',function() {
return {
restrict : 'E',
replace : true,
transclude: true,
scope : true,
template : '<li><a href="#" ng-click="showMeClicked()" ng-transclude></a></li>',
link: function(scope,element,doc) {
scope.showMeClicked = function() {
element[0].style.backgroundColor = 'red';
angular.element(element[0]).find('a').addClass('magic');
}
}
}
});
<div ng-app="myApp" ng-controller="MyController as vm">
<div ng-repeat="item in vm.items">
<clicker>{{item}}</clicker>
</div>
</div>
Upvotes: 2