Чи можу я зробити функцію доступною для кожного контролера в кутовому?


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 зробив цю роботу. Я хотів, щоб модуль перекладу був окрім програми, щоб я міг підключити його і до інших програм.
Пауло Педросо

Я б запропонував використовувати для цього конкретного випадку кутове значення, а не заводське, якщо ви не плануєте мати декілька функцій у сервісі. Якщо це лише одна функція, зробіть це значенням.
Ніколас Бласген

Я отримав помилку: [$ injector: 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>

7
Я думаю, що це повинна бути правильна відповідь, виправдана відповіддю @Praym. Немає сенсу вказувати залежність служби в 10 різних контролерах.
jvannistelrooy

Чи може служба включати методи / функції, які можуть властивості / змінні CRUD у $rootScope?
jezmck

44

Хоча перший підхід виступає як "кутовий" підхід, я вважаю, що це додає загальних витрат.

Подумайте, чи хочу я використовувати цю функцію myservice.foo у 10 різних контролерах. Мені доведеться вказати цю залежність 'myService', а потім $ властивість $ range.callFoo у всіх десяти з них. Це просто повторення і якимось чином порушує принцип DRY.

Якщо я використовую підхід $ rootScope, я визначаю цю глобальну функцію gobalFoo лише один раз, і вона буде доступна у всіх моїх майбутніх контролерах, незалежно від кількості.


5
Можливо, деяке значення має "документування" контролерів, де вони отримують цей глобальний виклик служби. Якби ти був одним із своїх контролерів в іншу програму, було б менш зрозуміло, звідки ця глобальна функція. Я чую, як визнаю ваш аргумент.
Меттью Пейн

Це має бути розміщено лише в тому випадку, якщо вам потрібно зателефонувати з точки зору. У контролері ви можете викликати його безпосередньо зі служби.
mcv

10
Це коментар, а не відповідь
Елліотт

Змінна $ rootScope завжди нульова на оновлення сторінки, і в цьому випадку функцію ви не отримаєте. Ось чому корисно ввести послугу та використовувати її посилання в додатку.
Ehsan Hafeez

4

AngularJs має " Послуги " та " Фабрики " лише для таких проблем, як ваша. Вони використовуються для того, щоб мати щось глобальне між контролерами, директивами, іншими службами чи будь-якими іншими компонентами angularjs. Ви можете визначати функції, зберігати дані, робити функції обчислення чи все, що вам потрібно хочете всередині служб і використовувати їх в AngularJs компоненти , як 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 і повісити ваші утилітні методи поза цим, щоб ви випадково не наступили на якусь іншу назву функції в величезне море речей, введених кутовими.
JE Carter II

Варто зазначити одне, і, можливо, чому це скасовано, ви можете використовувати лише ті функції у своїх шаблонах, а не ваші .ts модулі, оскільки ваші виклики функцій не вирішуються під час компіляції. Це причина робити це «кутовим» способом. Але, якщо ви просто хочете додати до своїх шаблонів декораторів і таких, глобальний файл утиліти простий і чудовий.
JE Carter II
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.