简体   繁体   中英

AngularJS - handle click events on existing DOM elements

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

(左边的节点树)

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.

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 });
        });
      });
    }
  };
}]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM