【问题标题】:Define function inside Angular directive's isolated scope在 Angularjs 指令隔离范围内定义函数
【发布时间】:2015-08-17 14:28:04
【问题描述】:

我正在编写一个自定义 <pagination> 指令,它将返回负责更改当前页面和分页设置的元素(例如,每页将显示多少项)。该指令具有隔离范围(使其更易于重用)。

在指令模板中,我需要调用像changePage()changePaginationSettings() 这样的函数。到目前为止,我发现在隔离范围内传递函数的唯一方法是在控制器中定义函数。

mainController.js

module.controller("mainController", function($scope) {
    $scope.changePage = function() { ... };
});

然后将其作为属性传递给指令:

pagination.js

module.directive("pagination", function() {
    return {
        restrict: "E",
        scope: {
           changePage: "="
        },
        templateUrl: "templates/pagination.html"
    }
}

pagination.html

<pagination change-page="changePage">

这对我来说看起来很丑陋,因为它将相关代码拆分为 2 个不相关的文件。也就是说changePage()函数应该定义在pagination.js文件中,而不是mainController.js中。

我认为这样的事情应该是可能的:

pagination.js

module.directive("pagination", function() {
    function changePage() { ... };

    return {
        restrict: "E",
        scope: {
           changePage: changePage
        },
        templateUrl: "templates/pagination.html"
    }
}

但是这样的代码会产生一个(对我来说毫无意义的)错误:Error: definition.match is not a function

有没有办法做到这一点?我的意思是在指令的隔离范围内传递同一文件中定义的函数。

我读过AngularJS Directive Docs,但他们甚至没有列出指令的scope 对象中的合法值是什么,只给出了一些“=”、“&”和“@”示例。

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    隔离范围对象定义的唯一合法值是以&amp;@= 开头的字符串。 (如果您希望属性名称在指令中有所不同,您也可以在这些符号后面加上父作用域上的属性名称。1)在这种情况下,您要使用 = 符号因为这表明 Angular 应该“将指令作用域上的 changePage 绑定到父作用域上的 changePage”。更多详情请查看this answer

    你是对的,通过指令上的属性传递这个函数是很丑陋的,但这是具有隔离作用域的本质。您可以考虑在服务中使用 changePage 和其他相关方法,因为您可以将其作为依赖项注入。

    编辑

    如果没有隔离作用域,您可以执行以下操作:

    module.directive("pagination", function() {    
        return {
            restrict: "E",
            templateUrl: "templates/pagination.html",
            link: function(scope, elem, attrs) {
                // scope.changePage is available from the directive's parent $scope
            }
        }
    }
    

    1 示例:{ 'nameInDirective': '=nameOnParent' }

    【讨论】:

    • 所以没有办法在指令本身内定义新的范围值,对吧?顺便说一句,我不认为允许这样做会违反 isolated scope 概念。使用服务的解决方案似乎比在控制器中定义值要好得多。感谢您的建议。
    • 您可以使用指令的$scope 做任何您喜欢的事情,与隔离作用域的唯一区别是指令继承您明确定义的属性,而不是其他人。像在控制器中一样访问指令的 $scope,例如:link: function(scope, elem, attrs) { ... }
    • 我在之前的评论中以错误的方式提出了这个问题。我的意思是:“所以没有办法在指令中定义一些新值? - 指令中唯一可用的值是通过属性传递给它的值绑定到隔离范围由我明确。”
    • 不确定您是否还在提问?但是,是的,这是正确的。
    • 是的,这是一个问题:)。我想确保我的想法是正确的。感谢您澄清并回答我的问题。
    【解决方案2】:

    当用户 sdgluck 正确回答时,您可以在链接函数中扩展指令范围,从而保持您的代码干净和独立。以下示例更完整一些,但归结为相同的结果。它允许您定义一个元素,如下所示。 请注意,所有属性都被解释为对象,并且,如果您想传递一个字符串值,您必须在该值周围加上额外的引号(否则您将获得该属性的未定义值)

    <my-button someattr="'my text'"></my-button>
    
    angular.module('test', []);
    
    angular.module('test').controller('testctrl', function($scope) {
      $scope.someValue = '';
    });
    
    angular.module('test').directive('myButton', function() {
      return {
        restrict: 'E',
        template: '<button>{{getText()}}</button>',
        replace: true,
        scope: {
          someattr: '='
        },
        link: function(scope, elements, attrs){
          scope.getText = function(){
            return scope.someattr;
          };
        }
      }
    });
    

    【讨论】:

      【解决方案3】:

      这里有一个示例配置。

      主控制器

      module.controller("mainController", function($scope) {
          $scope.changePage = function() { ... };
      });
      

      假设它是index.html,你应该有这样的指令

      <pagination change-page="changePage()">
      

      你的指令应该如下所示

      module.directive("pagination", function() {
          function changePage() { ... };
      
          return {
              restrict: 'E',
              scope: {
                 changePage: '&'
              },
              templateUrl: "templates/pagination.html"
          }
      }
      

      还有你的 pagination.html

      <div ng-click="changePage()"></div> 
      

      这将绑定到您的主控制器的changePage 函数。

      【讨论】:

      • 这与我提供的代码几乎相同。最重要的是你仍然在控制器中定义 changePage() 函数,这是我想避免的,也是我提出问题的原因 - 我问过有没有办法在指令中定义 changePage() 而不是比在控制器中。
      • 好的..无论如何你会在需要时错过隔离范围,因为你不能将参数从父范围传递给你的指令
      • 我不想从父范围传递任何东西。我想要的是在指令的隔离范围内定义一个新值(在我的情况下是一个函数)。
      【解决方案4】:

      我遇到了同样的问题,我在自定义指令中定义了我的函数,而不是在控制器中定义函数。 在这里你可以看到一个例子:

      您的 HTML:

      <my-custom-directive></my-custom-directive>
      

      你的指令定义:

      .directive("myCustomDirective", myCustomDirectiveHanlder)
      
      function myCustomDirectiveHandler() {
          return {
              templateUrl: "/app/templates/myCustomDirectiveTemplate.html",
              restrict: 'E',
              link: function (scope, elements, attrs) {
                  //your code here
              }
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-02
        • 1970-01-01
        相关资源
        最近更新 更多