0

I'm trying to capture a click event on a selection of existing DOM items using Angular:

(node tree on the left)

Here's the code:

<!-- HTML template (section) - it's a django template, i kept the django template syntax as original, using '{{' and '}}', and for AngularJS templating's system '{$' and '$}' --> <fieldset class="module aligned"> <h2>Document's sections</h2> <div class="form-row document-nodes" ng-app="DocumentNodesApp"> <div style="width: 100%; min-height: 450px;" ng-controller="NodeController" on-node-click="getNodeTitle($event)"> <form id="changelist-form" action="" method="post" novalidate>{% csrf_token %} <div id="tree" data-url="{{ tree_json_url }}" data-save_state="{{ app_label }}_documentnode" data-auto_open="{{ tree_auto_open }}" data-autoescape="{{ autoescape }}" > </div> </form> <div id="node-container"> {$node_title$} </div> </div> </div> </fieldset> /* DocumentNodeApp js code */ var app = angular.module('DocumentNodesApp', []); app.config(function($interpolateProvider) { $interpolateProvider.startSymbol('{$'); $interpolateProvider.endSymbol('$}'); }); var nodeController = app.controller( 'NodeController', function($scope){ $scope.node_title = "Click on a node..."; $scope.getNodeTitle = function(event){ alert(event); } }); app.directive( "onNodeClick", function(selector, $parse){ // connect the Angular context to the DOM events var linkFunction = function($scope, $element, $attrs){ //get the scope expression, will be evaluated on // the scope when the document is clicked var scopeExpression = $attrs.onNodeClick; var invoker = $parse(scopeExpression); $(selector).on("click", function(event){ $scope.$apply( function(){ invoker( $scope, { $event: event} ) } ); }); } return( linkFunction ); } ); 

After reloading the page, I have this error in console:

Error: [$injector:unpr] http://errors.angularjs.org/1.3.2/$injector/unpr?p0=selectorProvider%20%3C-%20selector%20%3C-%20onNodeClickDirective at Error (native) at http://127.0.0.1:8050/sitestatic/js/angular.min.js:6:416 at http://127.0.0.1:8050/sitestatic/js/angular.min.js:38:60 at Object.d [as get] (http://127.0.0.1:8050/sitestatic/js/angular.min.js:36:74) at http://127.0.0.1:8050/sitestatic/js/angular.min.js:38:132 at d (http://127.0.0.1:8050/sitestatic/js/angular.min.js:36:74) at Object.e [as invoke] (http://127.0.0.1:8050/sitestatic/js/angular.min.js:36:335) at http://127.0.0.1:8050/sitestatic/js/angular.min.js:47:393 at r (http://127.0.0.1:8050/sitestatic/js/angular.min.js:7:302) at Object.<anonymous> (http://127.0.0.1:8050/sitestatic/js/angular.min.js:47:360) angular.min.js:101 

Anyone has an idea of how to solve it? I just followed this guide on how to handle click events with AngularJS but it seems that doesn't work for me.

2
  • 1
    In your directive, you need to change "selector" to "$document" 1) function argument 2) $(selector) to $document Commented Nov 12, 2014 at 10:26
  • ok, and where i have to put the class selector for the dom elemets that i want? Commented Nov 12, 2014 at 10:28

1 Answer 1

2

If you just need to capture clicks on specific child elements of the element your on-node-click directive is attached to, you would, in your directive definition, attach the click listener to that element, and use the optional selector parameter in jQuery's .on() method to filter for just the child elements you want. You don't need to deal with $document at all.

So your directive would look like this:

.directive('onNodeClick', ['$parse', function ($parse) { return { restrict: 'A', link: function (scope, element, attrs) { var scopeExpresssion = attrs.onNodeClick, // gets string 'getNodeTitle($event)' from element attribute invoker = $parse(scopeExpresssion); // compile string into a function // listen for clicks on .node child elements element.on('click', '.node', function (e) { // wrap the function invocation in scope.$apply() so angular knows about it scope.$apply(function () { invoker(scope, { $event: e }); }); }); } }; }]); 

Here's a fiddle.

If, however, you really do need to capture click events on the document node like that article discusses, you just need to inject $document into your directive and attach the click listener to that instead of to the element that your directive is on.

In that case, your directive would look like this:

.directive('onNodeClick', ['$document', '$parse', function ($document, $parse) { return { restrict: 'A', link: function (scope, element, attrs) { var scopeExpresssion = attrs.onNodeClick, // gets string 'getNodeTitle($event)' from element attribute invoker = $parse(scopeExpresssion); // compile string into a function // listen for clicks on all .node elements within document $document.on('click', '.node', function (e) { // wrap the function invocation in scope.$apply() so angular knows about it scope.$apply(function () { invoker(scope, { $event: e }); }); }); } }; }]); 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.