it-roy-ru.com

Определить функцию внутри изолированной области видимости директивы Angular

Я пишу пользовательскую директиву <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, приводят только примеры "=", "&" и "@".

10
Robert Kusznier

Единственными допустимыми значениями для определения изолированного объекта области являются строки, которые начинаются с &, @ или =. (Вы также можете следовать за этими символами с именем свойства в родительской области, если вы хотите, чтобы имя свойства отличалось в директиве.1) В этом случае вы хотите использовать символ =, так как это означает, что Angular должен «связать changePage в области действия директивы с changePage в родительской области действия». Посмотрите на этот ответ для более подробной информации.

Вы правы в том, что некрасиво передавать эту функцию через атрибут в директиве, однако это характер изолированной области видимости. Вы можете рассмотреть возможность использования 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' }

12
sdgluck

Когда пользователь 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
Wim Van Houts

У меня была та же проблема, и я определил свою функцию внутри пользовательской директивы вместо определения функции внутри контроллера ........ Здесь вы можете увидеть пример:

Ваш 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
        }
    }
};
0
Lorena Pita

здесь у вас есть пример конфигурации.

главный контроллер

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.

0
bews99