146 votes

Comment puis-je ajouter de petites fonctions utilitaires à mon application AngularJS?

Je voudrais ajouter quelques fonctions utilitaires pour mon application AngularJS. Par exemple:

$scope.isNotString = function (str) {
    return (typeof str !== "string");
}

Est la meilleure façon de le faire pour les ajouter en tant que service? De ce que j'ai lu que je peux faire mais ensuite, je voudrais de les utiliser dans mes pages HTML ainsi est-il encore possible si ils sont dans un service? Par exemple puis-je utiliser les éléments suivants:

 <button data-ng-click="doSomething()"
         data-ng-disabled="isNotString(abc)">Do Something
 </button>

Quelqu'un peut-il me donner un exemple de la façon dont je pourrais ajouter ces. Dois-je créer un service ou est-il un autre moyen de le faire. Le plus important, je voudrais que ces utilitaire les fonctions dans un fichier et non en combinaison avec une autre partie de l'ensemble principal.

Je comprends, il y a plusieurs solutions, mais aucune n'est aussi clair.

Solution 1 - Proposé par Urban

$scope.doSomething = ServiceName.functionName;

Le problème ici c'est que j'ai 20 fonctions et dix contrôleurs. Si j'ai fait ceci, cela signifie l'ajout de beaucoup de code pour chaque contrôleur.

Solution 2 - Proposé par moi

    var factory = {

        Setup: function ($scope) {

            $scope.isNotString = function (str) {
                return (typeof str !== "string");
            }

L'inconvénient de cette est que, au début de chaque contrôleur, j'aurais un ou plusieurs de ces appels d'Installation pour chaque service qui a passé l' $champ d'application.

Solution 3 - Proposé par Urban

La solution proposée par la croissance urbaine, de la création d'un service générique semble bon. Voici mon jeu principal:

var app = angular
    .module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
    .config(['$locationProvider', '$sceProvider', '$stateProvider',
        function ($locationProvider, $sceProvider, $stateProvider) {

            $sceProvider.enabled(false);
            $locationProvider.html5Mode(true);

Dois-je ajouter le service générique de ce et comment pourrais-je le faire ?

106voto

urban_racoons Points 1452

EDIT 2/3/14:

Après avoir réfléchi à ce sujet et de lire les autres réponses, en fait, je crois que je préfère une variante de la méthode apporté par @Brent Washburne et @Amogh Talpallikar. Surtout si vous êtes à la recherche pour les services publics, comme isNotString() ou similaire. L'un des avantages est que vous pouvez les utiliser de nouveau à l'extérieur de votre angulaire de code et vous pouvez les utiliser à l'intérieur de votre fonction config (que vous ne pouvez pas faire avec services).

Cela étant dit, si vous êtes à la recherche d'une méthode générique permettant de ré-utiliser ce que devraient être des services, le vieux la réponse, je pense, est toujours un bon.

Ce que je voudrais faire maintenant, c'est:

app.js:

var MyNamespace = MyNamespace || {};

 MyNamespace.helpers = {
   isNotString: function(str) {
     return (typeof str !== "string");
   }
 };

 angular.module('app', ['app.controllers', 'app.services']).                             
   config(['$routeProvider', function($routeProvider) {
     // Routing stuff here...
   }]);

controller.js:

angular.module('app.controllers', []).                                                                                                                                                                                  
  controller('firstCtrl', ['$scope', function($scope) {
    $scope.helpers = MyNamespace.helpers;
  });

Puis dans votre partiel, vous pouvez utiliser:

<button data-ng-click="console.log(helpers.isNotString('this is a string'))">Log String Test</button>

Vieille réponse ci-dessous:

Il pourrait être préférable de les inclure en tant que service. Si vous allez à les réutiliser sur plusieurs contrôleurs, y compris comme un service qui va vous éviter d'avoir à répéter de code.

Si vous souhaitez utiliser les fonctions de service dans votre code html partielle, alors vous devez les ajouter à celle du contrôleur de la portée:

$scope.doSomething = ServiceName.functionName;

Puis dans votre partiel, vous pouvez utiliser:

<button data-ng-click="doSomething()">Do Something</button>

Voici une façon que vous pouvez garder cette, le tout organisé et sans trop de tracas:

Distinct de votre contrôleur, le service et le code de routage/config en trois fichiers: controllers.js, services.js et app.js. La couche supérieure du module "application", qui a app.les contrôleurs et les app.des services comme des dépendances. Puis app.les contrôleurs et les app.les services peuvent être déclarés sous forme de modules dans leurs propres fichiers. Cette structure organisationnelle est juste de prendre du Angulaire de la Graine:

app.js:

 angular.module('app', ['app.controllers', 'app.services']).                             
   config(['$routeProvider', function($routeProvider) {
     // Routing stuff here...
   }]);  

services.js:

 /* Generic Services */                                                                                                                                                                                                    
 angular.module('app.services', [])                                                                                                                                                                        
   .factory("genericServices", function() {                                                                                                                                                   
     return {                                                                                                                                                                                                              
       doSomething: function() {   
         //Do something here
       },
       doSomethingElse: function() {
         //Do something else here
       }
    });

controller.js:

angular.module('app.controllers', []).                                                                                                                                                                                  
  controller('firstCtrl', ['$scope', 'genericServices', function($scope, genericServices) {
    $scope.genericServices = genericServices;
  });

Puis dans votre partiel, vous pouvez utiliser:

<button data-ng-click="genericServices.doSomething()">Do Something</button>
<button data-ng-click="genericServices.doSomethingElse()">Do Something Else</button>

De cette façon, vous seulement ajouter une ligne de code pour chaque contrôleur et sont en mesure d'accéder à toutes les fonctions de services où celui-ci est accessible.

6voto

Willis Blackburn Points 980

Ai-je bien compris que vous voulez juste définir quelques méthodes utilitaires et les rendre disponibles dans les modèles ?

Vous n’avez pas à ajouter à chaque contrôleur. Juste définir un régulateur unique pour toutes les méthodes utilitaires et fixez ce contrôleur à ou (en utilisant la directive ngController). Tous les autres contrôleurs vous attacher n’importe où sous (ce qui signifie que n’importe où, période) ou) héritera de cette $scope et auront accès à ces méthodes.

4voto

Brent Washburne Points 2453

La façon la plus simple pour ajouter des fonctions de l'utilitaire de est de les laisser à l'échelle mondiale:

function myUtilityFunction(x) { return "do something with "+x; }

Ensuite, la façon la plus simple d'ajouter une fonction d'utilité (un contrôleur) est de l'attribuer à l' $scope, comme ceci:

$scope.doSomething = myUtilityFunction;

Ensuite, vous pouvez l'appeler comme ceci:

{{ doSomething(x) }}

ou comme ceci:

ng-click="doSomething(x)"

EDIT:

La question initiale est de savoir si le meilleur moyen d'ajouter une fonction d'utilité est par le biais d'un service. Je n'en dis pas, si la fonction est assez simple (comme l' isNotString() exemple fourni par l'OP).

Les avantages de l'écriture d'un service est de le remplacer par un autre (par injection) pour le but de les tester. Poussées à l'extrême, avez-vous besoin d'injecter de chaque fonction d'utilité dans votre contrôleur?

La documentation dit tout simplement de définir le comportement du contrôleur (comme $scope.double): http://docs.angularjs.org/guide/controller

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X