Reputation: 6877
The scope variables updated by the directive are not reflected where we have {{variable}}
on the page, however they do show up as being updated in when I do console.log(scope)
.
<script>
var demoApp = angular.module('demoApp', []);
demoApp.controller('demoController', function demoController($scope) {
$scope.myElementId ="abcd";
$scope.updateVals = function() {
$scope.myElementClass = "";
};
});
demoApp.directive('demoSelect', function() {
return {
restrict: 'A',
controller: 'demoController',
link: function(scope, element, attrs, controller) {
element.on("click", function(event) {
event.stopImmediatePropagation();
event.preventDefault();
scope.ele = angular.element(event.target);
angular.element(".selected").removeClass("selected");
$(scope.ele).addClass("selected");
var mm = $(scope.ele).get(0);
scope.myElementId = $(scope.ele).attr("id");
scope.myElementClass = $(scope.ele).attr("class");
scope.myElementType = mm.tagName;
});
}
};
});
</script>
Here is the plunker for it. What am I missing?
Upvotes: 4
Views: 5921
Reputation: 48212
There were a couple of errors in your demo:
jQuery was loaded after Angular. You should always load jQuery before Angular, so the latter is aware of and can take advantage of the former.
The automatic dash-delimited to camelCase convertion is applied only to directives, not the names of your apps or controllers. Thus, you should write demoApp
and demoController
, instead of demo-app
and demo-controller
in your HTML.
You were calling some Angular-specific code (updating values in the Scope) from an non-Angular context (jQuery event callback), so in order for having the changes processed by Angular (and the results propagated to the view), you must enclose the relevant code into scope.$apply().
(This is not an error technically, but): You were converting some jQuery objects to jQuery objects again. This instroduces unnecessary overhead and should be avoided.
Taking into account the above, your directive's link function's body should look something like this:
element.on('click' , function(evt) {
evt.stopImmediatePropagation();
evt.preventDefault();
$('.selected').removeClass('selected');
element.addClass('selected');
scope.$apply(function () {
scope.myElementId = attrs.id;
scope.myElementClass = attrs.class;
scope.myElementType = element.prop('tagName');
});
});
See, also, this woking demo.
Upvotes: 6
Reputation: 366
Your link function should look like this:
link: function(scope, element, attrs, controller) {
element.on("click", function(event) {
event.stopImmediatePropagation();
event.preventDefault();
$(".selected").removeClass("selected");
$(element).addClass("selected");
var mm = $(element).get(0);
scope.myElementId = $(element).attr("id");
scope.myElementClass = $(element).attr("class");
scope.myElementType = mm.tagName;
});
}
Also you have an error in your code. Take care of camelcase names for controller and app.
Upvotes: 2
Reputation: 26930
Use scope.$apply
:
scope.$apply(function(){
scope.ele = angular.element(event.target);
angular.element(".selected").removeClass("selected");
$(scope.ele).addClass("selected");
var mm = $(scope.ele).get(0);
scope.myElementId = $(scope.ele).attr("id");
scope.myElementClass = $(scope.ele).attr("class");
scope.myElementType = mm.tagName;
});
You need this because you are modifying scope variables inside event and angularjs does not update dom in this case
Upvotes: 4