Могу ли я сделать функцию доступной в каждом контроллере в угловом режиме?

191

Если у меня есть служебная функция, fooкоторую я хочу вызывать из любой точки моего ng-appобъявления. Можно ли как-нибудь сделать его глобально доступным в настройках моего модуля или мне нужно добавить его в область действия каждого контроллера?

Людвиг Магнуссон
источник
Я не уверен на 100% в этом, но есть вероятность, что вы также можете определить его в своем модуле следующим образом: module.value('myFunc', function(a){return a;});и затем внедрить его по имени в ваши контроллеры. (Если кто-то хочет избежать предоставления услуги)
user2173353
Это означает, что я должен добавить его к каждому контроллеру вручную. $ rootScope - это то, что я хотел сделать почти 2 года назад =)
Людвиг Магнуссон,
ХОРОШО. :) Я просто использую директивы с изолированной областью действия чаще, чем простые контроллеры, и мне все равно приходится вводить все. Мне нравится стиль модульного кода, который это обеспечивает. Кроме того, вам не нужно связываться с родительскими областями каким-либо образом, и вам не нужно много искать, откуда берутся ваши переменные области видимости. :)
user2173353

Ответы:

290

В основном у вас есть два варианта: либо определить его как службу, либо поместить в корневую область. Я бы посоветовал вам сделать из этого сервис, чтобы не загрязнять корневую область. Вы создаете сервис и делаете его доступным в вашем контроллере следующим образом:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.factory('myService', function() {
        return {
            foo: function() {
                alert("I'm foo!");
            }
        };
    });

    myApp.controller('MainCtrl', ['$scope', 'myService', function($scope, myService) {
        $scope.callFoo = function() {
            myService.foo();
        }
    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="callFoo()">Call foo</button>
</body>
</html>

Если это не вариант для вас, вы можете добавить его в корневую область следующим образом:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.run(function($rootScope) {
        $rootScope.globalFoo = function() {
            alert("I'm global foo!");
        };
    });

    myApp.controller('MainCtrl', ['$scope', function($scope){

    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="globalFoo()">Call global foo</button>
</body>
</html>

Таким образом, все ваши шаблоны могут вызывать globalFoo()без необходимости передавать его в шаблон из контроллера.

Андерс Экдаль
источник
5
В первом решении, что, если есть тонны foo()функций? Создание $scope.callFoo()обертки для каждого из них - это слишком много работы. Как я могу «прикрепить» все функции библиотеки в область видимости, чтобы ее можно было использовать в шаблоне? У меня есть большая библиотека преобразования единиц измерения, и я хочу, чтобы она была доступна в моем шаблоне.
AlexStack
3
Мой вопрос также. Я попробовал это, и это работает: вы можете «прикрепить» его, сказав $scope.callFoo = myService.foo;вместо создания новой оболочки в каждом месте, где вы хотите его использовать.
Fitter Man
1
Спасибо за вашу помощь, мне было интересно, как сделать доступной функцию смены языка в моем приложении, и $ rootScope справился со своей задачей. Я хотел отделить модуль перевода от приложения, чтобы подключить его и к другим приложениям.
Пауло Педросо
Я бы рекомендовал использовать угловое значение, а не заводское значение для этого конкретного случая, если только вы не планируете иметь несколько функций внутри службы. Если это только одна функция, сделайте ее Value.
Николас Блазген
Я получил ошибку: [$ инжектор: unpr]
Марк Тхиен
53

Вы также можете объединить их, я думаю:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
</body>
</html>
RIC
источник
7
Я думаю, что это должен быть правильный ответ, оправданный ответом @Praym. Не имеет смысла указывать сервисную зависимость в 10 разных контроллерах.
jvannistelrooy
Может ли служба включать методы / функции, которые могут CRUD-свойства / переменные в $rootScope?
jezmck
44

Хотя первый подход пропагандируется как «угловой», я чувствую, что это добавляет накладных расходов.

Подумайте, хочу ли я использовать эту функцию myservice.foo в 10 различных контроллерах. Мне нужно будет указать эту зависимость 'myService', а затем свойство области действия $ scope.callFoo во всех десяти из них. Это просто повторение и как-то нарушает принцип СУХОЙ.

Принимая во внимание, что если я использую подход $ rootScope, я указываю эту глобальную функцию gobalFoo только один раз, и она будет доступна во всех моих будущих контроллерах, независимо от того, сколько.

Praym
источник
5
Может быть некоторое значение в «документировании» контроллеров, где они получают этот глобальный сервисный вызов. Если бы вы включили один из ваших контроллеров в другое приложение, было бы менее понятно, откуда взялась эта глобальная функция. Я слышу, узнаю ваш аргумент, хотя.
Мэтью Пейн
Это только должно быть помещено в область, если вам нужно вызвать это из представления. В контроллере вы можете позвонить прямо из сервиса.
MCV
10
Это комментарий, а не ответ
Эллиотт
Переменная $ rootScope всегда обновляется при обновлении страницы, в этом случае вы не получите функцию. Поэтому полезно внедрить сервис и использовать его ссылку в приложении.
Эхсан Хафиз,
4

AngularJs имеет « Службы » и « Фабрики » только для таких задач, как ваша. Они используются для того, чтобы иметь что-то глобальное между контроллерами, директивами, другими службами или любыми другими компонентами angularjs. Вы можете определять функции, хранить данные, выполнять функции вычисления или что угодно хочу внутри Сервисов и использовать их в AngularJs Components как Global .like

angular.module('MyModule', [...])
  .service('MyService', ['$http', function($http){
    return {
       users: [...],
       getUserFriends: function(userId){
          return $http({
            method: 'GET',
            url: '/api/user/friends/' + userId
          });
       }
       ....
    }
  }])

если вам нужно больше

Узнайте больше о том, зачем нам нужны сервисы и фабрики AngularJs

Азарапет Туанян
источник
0

Я немного новичок в Angular, но мне показалось полезным (и довольно простым) то, что я создал глобальный скрипт, который загружаю на свою страницу перед локальным скриптом с глобальными переменными, к которым мне все равно нужно обращаться на всех страницах. В этом сценарии я создал объект с именем globalFunctions и добавил функции, к которым мне нужен глобальный доступ в качестве свойств. например globalFunctions.foo = myFunc();. Затем в каждом локальном сценарии я написал$scope.globalFunctions = globalFunctions; и сразу получил доступ к любой функции, добавленной в объект globalFunctions в глобальном сценарии.

Это немного обходной путь, и я не уверен, что это поможет вам, но это определенно помогло мне, так как у меня было много функций, и было неудобно добавлять их все на каждую страницу.

Иззи
источник
1
Мне просто любопытно, почему отрицательные голоса? Я новичок и хотел бы узнать от профи.
Иззи
Похоже, рабочее решение для меня. Единственное, что я бы рекомендовал, чтобы убедиться, что ваша область достаточно изолирована, - это создать глобальный корневой служебный класс Javascript и отключить от него ваши служебные методы, чтобы вы случайно не наступили на какое-то другое имя функции в Огромное море вещей, введенных Angular.
Картер II
Стоит отметить одну вещь, и, возможно, почему это не рекомендуется, вы можете использовать эти функции только в своих шаблонах, а не в своих модулях .ts, поскольку вызовы функций не будут разрешаться во время компиляции. Это причина сделать это «угловым» способом. Но если вы просто хотите добавить декораторы и тому подобное к своим шаблонам, глобальный служебный файл прост и хорош.
Картер II