在Angular指令的隔离范围内定义函数

时间:2015-08-17 14:28:04

标签: angularjs angularjs-directive angularjs-scope

我正在编写自定义<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对象中的合法值,只给出一些&#34; =&#34; ,&#34;&amp;&#34;和&#34; @&#34;实例

4 个答案:

答案 0 :(得分:12)

隔离范围对象定义的唯一合法值是以&@=开头的字符串。 (如果您希望属性名称在指令中有所不同,也可以在父作用域上使用属性名称跟随这些符号。 1 )在此实例中,您希望使用{{1} }这表示Angular应该将指令范围上的=绑定到父范围&#34;上的changePage。有关详细信息,请查看this answer

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

修改

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

changePage

1 示例: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 :(得分: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;
      };
    }
  }
});

答案 2 :(得分:0)

这里有一个示例配置。

主控制器

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功能。

答案 3 :(得分:0)

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

您的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
        }
    }
};