javascript AngularJS ng-click 不在范围内调用函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20021861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 17:31:54  来源:igfitidea点击:

AngularJS ng-click not calling function on scope

javascriptangularjs

提问by David Pugh

I have a custom directive which loads a navigation block from a webservice call. I am trying to click on one of those navigation links which I put a "ng-click" in. I am trying to click on the link which should call the function called within the ng-click. That function should execute, but it is not.

我有一个自定义指令,它从 web 服务调用加载导航块。我试图点击其中一个我放入“ng-click”的导航链接。我试图点击应该调用在 ng-click 中调用的函数的链接。该函数应该执行,但事实并非如此。

Here is my routing

这是我的路由

var cartangularPublicShoppingApp = angular.module('cartangularPublicShoppingApp', [
  'ngRoute',
  'CategoriesController',
  'CategoryServices',
  'CategoryNavigationServices',
  'MenuModule'
]);
cartangularPublicShoppingApp.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/cart', {
                templateUrl: 'partials/public/cart.html',
                controller: 'CartCtrl'
            }).
            when('/categories/:categoryId', {
                templateUrl: 'partials/public/categories.html',
                controller: 'CategoriesController'
            }).
            otherwise({
                redirectTo: '/categories'
            });
    }]
);

Here is the custom directive

这是自定义指令

angular.module('MenuModule', [])
.directive('myCustomer', function() {
        return {
            restrict: 'E',
            templateUrl: './partials/public/customer.html',
            controller: function($scope, $sce, CategoryNavigationService) {

                var z = CategoryNavigationService.getCategoryNavigation().success(function(data){
                    $scope.categoryNavigation = data;
                    var navHTML = createCategoryNavigationBar(data);
                    var t = $sce.trustAsHtml(navHTML);
                    $scope.panes = t;

                }).error(function(data){

                        var error = "Get confident, stupid!";
                        var t = $sce.trustAsHtml(error);
                        $scope.panes = t;
                });
                function createCategoryNavigationBar(categoryNavigation){
                     var test = "";
                    var categoryId;
                    var catNavArray = categoryNavigation.categoryNavigationArray;
                     for(categoryId in catNavArray){
                         var currentCategoryNavigation = categoryNavigation.categoryNavigationArray[categoryId];
                            var string =  '<li> <a href="javascript:void(0);" name="categoryId" ng-click="getProductsForCategory()">' + currentCategoryNavigation.categoryName + "</a>";
                            test = test + string;

                         var count = 0;
                         var countingNavArr = currentCategoryNavigation.categoryNavigationArray;
                         for(var countingObject in countingNavArr){
                             count++;
                         }
                         if(count > 0){
                             var innerCategoryId;
                             test = test + "<ul>";
                             for(innerCategoryId in currentCategoryNavigation.categoryNavigationArray){
                                 var innerCategoryNavigation = currentCategoryNavigation.categoryNavigationArray[innerCategoryId];
                                 var innerTest = createCategoryNavigationBar(innerCategoryNavigation);
                                 test = test + innerTest;
                             }
                             test = test + "</ul>";
                         }
                         test = test + "</li>";
                    }
                    test = '<ul id="menu">' + test + '</ul>';
                    return test;



                }

            }
        };
    });

Here is the controller that get's routed to my html fragment that I am showing the directive in.

这是路由到我在其中显示指令的 html 片段的控制器。

var categoriesControllers = angular.module('CategoriesController', []);

categoriesControllers.controller('CategoriesController', ['$scope', '$routeParams' , '$location', 'CategoryService',
  function($scope, $routeParams, $location, CategoryService) {

      var categoryId = $routeParams.categoryId;
      getProductsByCategoryIdServiceCall(CategoryService, categoryId);

      $scope.getProductsForCategory = function(){
          var categoryId = 4;
          getProductsByCategoryIdServiceCall(CategoryService, categoryId);

      }
      function getProductsByCategoryIdServiceCall(CategoryService, categoryId){
          CategoryService.getProductsByCategoryId(categoryId).success(function(data){
              $scope.productsDTO = data;
              $scope.name = "David M Pugh";
          }).error(function(data){
                  $scope.name = "David Q Pugh";
                  $scope.name = data;
          });

      }

  }]);

Here is code fragment from categories.html that contains the custom directive:

以下是来自 category.html 的代码片段,其中包含自定义指令:

   <div class="row-fluid">
        <div class="span12">
            <div class="navbar">
                <div class="navbar-inner">
                    <div class="container" style="width: auto;">
                        <div class="span5"></div>
                        <div class="span2">
                            <div id="currentCategoryDropBoxMenu">

                            </div>
                        </div>

                    </div>
                </div>
            </div>
        </div>
    </div>
    <br />
  <my-customer></my-customer>
    <br />

I have tried changing the javascript method called inside ng-click to be like: ng-click="getProductsForCategory" as well.

我也尝试将 ng-click 中调用的 javascript 方法更改为: ng-click="getProductsForCategory" 。

both results in the method getProductsForCategory not being called when the link is clicked

两者都导致单击链接时未调用 getProductsForCategory 方法

Does anyone have any idea what my problem is?

有谁知道我的问题是什么?

thanks,

谢谢,

David

大卫

EDITED INFO*Hey folks, thanks for looking into this problem. It is still ongoing, but I added an extra test to my html fragment for my custom directive

编辑信息* 大家好,感谢您调查这个问题。它仍在进行中,但我为我的自定义指令添加了一个额外的测试到我的 html 片段

<div ng-bind-html="panes"></div>
<a href="javascript:void(0);" ng-click="getProductsForCategory()">testing</a>

Before the only line was the first tag which was the div. I added the 2nd line to see if it was perhaps the binding of the html directly to the div tag in the directive, or if there was a problem with the directive's configuration elsewhere.

在唯一的一行之前是第一个标签,即 div。我添加了第 2 行,看看它是否可能是 html 直接绑定到指令中的 div 标签,或者指令在其他地方的配置是否有问题。

The second tag I added should be a standard ng-click operation. my 2nd a href tag does call the function getProductsForCategory(). So it does appear to be due to my binding of my html string to the div element for the directive.

我添加的第二个标签应该是标准的 ng-click 操作。我的第二个 href 标签确实调用了函数 getProductsForCategory()。所以这似乎是由于我将 html 字符串绑定到指令的 div 元素。

The problem is that my navigation structure i am building can have infinite nested child elements (it's basically a suckerfish select box).

问题是我正在构建的导航结构可以有无限的嵌套子元素(它基本上是一个吸盘选择框)。

This means I will have to use recursion to map out every parent child navigation structure...in a directive...

这意味着我将不得不使用递归来映射出每个父子导航结构......在指令中......

采纳答案by David Pugh

I came up with a solution for my project. Here is the routing section

我为我的项目想出了一个解决方案。这是路由部分

var cartangularPublicShoppingApp = angular.module('cartangularPublicShoppingApp', [
  'ngRoute',
  'CategoriesController',
  'CategoryServices',
  'CategoryNavigationServices',
  'MenuModule'
]);
cartangularPublicShoppingApp.config(['$routeProvider',
    function($routeProvider) {
        $routeProvider.
            when('/categories/:categoryId', {
                templateUrl: 'partials/public/categories.html',
                controller: 'CategoriesController'
            })
    }]
);


This is the main controller for the view (categories.html) that will be used to show off our custom directive. I created a test dataset called "treeFamily" that I will use to test the directive in this controller

这是视图 (categories.html) 的主要控制器,用于展示我们的自定义指令。我创建了一个名为“treeFamily”的测试数据集,我将用它来测试这个控制器中的指令

var categoriesControllers = angular.module('CategoriesController', []);

categoriesControllers.controller('CategoriesController', ['$scope', '$routeParams' , '$location', 'CategoryService',
  function($scope, $routeParams, $location, CategoryService) {

      $scope.treeFamily = {
          name : "Clothes",
          categoryId : "4",
          children: [{
              name : "Clothes",
              categoryId : "3",
              children: [{
                  name : "Men's Clothes",
                  categoryId : "2",
                  children: []
              },{
                  name : "Hymanets",
                  categoryId : "1",
                  children: [
                      {
                          name : "Light Hymanets",
                          categoryId : "4",
                          children: [{
                              name : "Natural Material",
                              children: []
                          }
                          ]
                      },{
                          name : "Heavy Hymanets",
                          categoryId : "3",
                          children: []
                      }]
              }, {
                  name: "Pants",
                  categoryId : "4",
                  children: []
              }]
          }]
      }


Here is the directive that we will use to recursively traverse our dataset.

这是我们将用于递归遍历数据集的指令。

angular.module('MenuModule', [])
.directive("tree", function(RecursionHelper) {
    return {
        restrict: "E",
        scope: {
            family: '=',
            'product': '&products'
       },

        templateUrl: './partials/public/family.html',
        compile: function(element) {
            return RecursionHelper.compile(element);
        }
    };
})


This is a compiling service that I found someone demonstrating online. I decided to use it, as it keeps our code neat and clean.

这是我发现有人在网上演示的编译服务。我决定使用它,因为它使我们的代码保持整洁。

var categoryNavigationServices = angular.module('CategoryNavigationServices', []);
categoryNavigationServices.factory('RecursionHelper', ['$compile', function($compile){
    var RecursionHelper = {
        compile: function(element){
            var contents = element.contents().remove();
            var compiledContents;
            return function(scope, element){
                if(!compiledContents){
                    compiledContents = $compile(contents);
                }
                compiledContents(scope, function(clone){
                    element.append(clone);
                });
            };
        }
    };

    return RecursionHelper;
}]);


This is the html fragment for our directive. Note how we are calling the directive from within the directive.

这是我们指令的 html 片段。请注意我们如何从指令内部调用指令。

<a href="javascript:void(0);" name="categoryId" ng-click="product(family.categoryId)">{{ family.name }}</a>
<ul>
    <li ng-repeat="child in family.children">
        <tree family="child"  products="products(child.categoryId)"></tree>
    </li>
</ul>


Here is part of my categories.html page which is the main view from my controller.

这是我的 category.html 页面的一部分,它是我的控制器的主视图。

    <ul>
            <li ng-repeat="object in treeFamily.children">
                <a href="javascript:void(0);" name="categoryId" ng-click="products(object.categoryId)">{{object.name}}</a>
                <ul>
                    <li ng-repeat="child in object.children">
                        <tree family="child" products="products(child.categoryId)"></tree>

                    </li>
                </ul>
            </li>
   </ul>


The main problem I was having after i got the recursive directives working was that my ng-click that I added to the directive's html was not responding when clicked. This was because the scope on the directive was an isolated scope.

我在递归指令工作后遇到的主要问题是,我添加到指令的 html 中的 ng-click 在单击时没有响应。这是因为指令的作用域是一个孤立的作用域。

In order to access the main controller's method, you have to bind the directive's method to the controller's method. in order to do this you have to add the controller's function you want to bind to within the tag its'self. ie:

为了访问主控制器的方法,您必须将指令的方法绑定到控制器的方法。为了做到这一点,您必须在标签本身中添加要绑定到的控制器功能。IE:

<tree family="child" products="products(child.categoryId)">

and the directive's isolated scope references this ie:

并且指令的隔离范围引用了这个,即:

scope: {
            family: '=',
            'product': '&products'
       },

The a href inside the directive's html is as such:

指令的 html 中的 a href 是这样的:

<a href="javascript:void(0);" name="categoryId" ng-click="product(family.categoryId)">{{ family.name }}</a>

note that we reference the directive's function "product", and not products, which is the name of the method on the controller that we wanted access to.

请注意,我们引用了指令的函数“product”,而不是 products,它是我们想要访问的控制器上的方法的名称。

回答by charlietfl

You are missing a set of braces in ng-clickmarkup

您在ng-click标记中缺少一组大括号

ng-click="getProductsForCategory"

ng-click="getProductsForCategory"

Should be

应该

ng-click="getProductsForCategory()"

回答by Maxim Shoustin

The one thing that seems problematic that you didn't compile HTML in directive. This is a reason that ng-clickdoesn't work because angular doesn't see this change.

似乎有问题的一件事是您没有在指令中编译 HTML。这是一个ng-click不起作用的原因,因为 angular 看不到这种变化。

var string =  '<li> <a href="" name="categoryId" ng-click="getProductsForCategory()">' + currentCategoryNavigation.categoryName + "</a>";

when you call:

你打电话的时候:

 var navHTML = createCategoryNavigationBar(data);

try to write something like:

尝试写一些类似的东西:

var temp = createCategoryNavigationBar(data);
var navHTML = angular.element(temp)($scope));

maybe it will help,

也许它会有所帮助,