Je voudrais ajouter quelques fonctions utilitaires à mon application AngularJS. Par exemple:
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
La meilleure façon de procéder est-elle de les ajouter en tant que service? D'après ce que j'ai lu, je peux le faire, mais j'aimerais les utiliser dans mes pages HTML, est-ce donc toujours possible s'ils sont dans un service? Par exemple, puis-je utiliser ce qui suit:
<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 les ajouter. Dois-je créer un service ou y a-t-il une autre façon de le faire? Le plus important, je voudrais ces fonctions utilitaires dans un fichier et non combinées avec une autre partie de la configuration principale.
Je comprends qu'il existe quelques solutions, mais aucune d'elles n'est aussi claire.
Solution 1 - Proposée par Urban
$scope.doSomething = ServiceName.functionName;
Le problème ici est que j'ai 20 fonctions et dix contrôleurs. Si je faisais cela, cela signifierait ajouter beaucoup de code à chaque contrôleur.
Solution 2 - Proposé par moi
var factory = {
Setup: function ($scope) {
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
L'inconvénient est qu'au début de chaque contrôleur, j'aurais un ou plusieurs de ces appels de configuration à chaque service qui a passé la portée $.
Solution 3 - Proposée par Urban
La solution proposée par urban de créer un service générique semble bonne. Voici ma configuration principale:
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 à cela et comment pourrais-je le faire?
Réponses:
EDIT 7/1/15:
J'ai écrit cette réponse il y a assez longtemps et je n'ai pas beaucoup suivi angular depuis un moment, mais il semble que cette réponse soit encore relativement populaire, alors je voulais souligner que quelques-uns des points @nicolas les marques ci-dessous sont bonnes. D'une part, injecter $ rootScope et y attacher les helpers vous évitera d'avoir à les ajouter pour chaque contrôleur. Aussi - je conviens que si ce que vous ajoutez doit être considéré comme des services OU des filtres angulaires, ils doivent être adoptés dans le code de cette manière.
De plus, à partir de la version actuelle 1.4.2, Angular expose une API "Provider", qui est autorisée à être injectée dans les blocs de configuration. Consultez ces ressources pour en savoir plus:
https://docs.angularjs.org/guide/module#module-loading-dependencies
Injection de dépendance AngularJS de valeur à l'intérieur de module.config
Je ne pense pas que je vais mettre à jour les blocs de code réels ci-dessous, car je n'utilise pas vraiment activement Angular ces jours-ci et je ne veux pas vraiment risquer une nouvelle réponse sans me sentir à l'aise avec le fait qu'elle se conforme réellement au nouveau meilleur les pratiques. Si quelqu'un d'autre se sent à la hauteur, allez-y.
MODIFIER 2/3/14:
Après avoir réfléchi à cela et lu certaines des autres réponses, je pense en fait que je préfère une variante de la méthode évoquée par @Brent Washburne et @Amogh Talpallikar. Surtout si vous recherchez des utilitaires comme isNotString () ou similaire. L'un des avantages évidents ici est que vous pouvez les réutiliser en dehors de votre code angulaire et vous pouvez les utiliser à l'intérieur de votre fonction de configuration (ce que vous ne pouvez pas faire avec les services).
Cela étant dit, si vous cherchez un moyen générique de réutiliser ce qui devrait être correctement des services, je pense que l'ancienne réponse est toujours bonne.
Ce que je ferais maintenant, c'est:
app.js:
controller.js:
Ensuite, dans votre partiel, vous pouvez utiliser:
Ancienne réponse ci-dessous:
Il serait peut-être préférable de les inclure en tant que service. Si vous allez les réutiliser sur plusieurs contrôleurs, les inclure en tant que service vous évitera d'avoir à répéter le code.
Si vous souhaitez utiliser les fonctions de service dans votre partiel html, vous devez les ajouter à la portée de ce contrôleur:
$scope.doSomething = ServiceName.functionName;
Ensuite, dans votre partiel, vous pouvez utiliser:
Voici un moyen de garder tout cela organisé et sans trop de tracas:
Séparez votre contrôleur, service et code / configuration de routage en trois fichiers: controllers.js, services.js et app.js. Le module de couche supérieure est "app", qui a app.controllers et app.services comme dépendances. Ensuite, app.controllers et app.services peuvent être déclarés en tant que modules dans leurs propres fichiers. Cette structure organisationnelle est juste tirée de Angular Seed :
app.js:
services.js:
controller.js:
Ensuite, dans votre partiel, vous pouvez utiliser:
De cette façon, vous n'ajoutez qu'une seule ligne de code à chaque contrôleur et pouvez accéder à toutes les fonctions des services partout où cette portée est accessible.
la source
En venant sur ce vieux fil, je voulais souligner que
1 °) des fonctions utilitaires peuvent (devraient?) Être ajoutées au rootscope via module.run. Il n'est pas nécessaire d'instancier un contrôleur de niveau racine spécifique à cette fin.
2 °) Si vous organisez votre code en modules séparés vous devez utiliser des services angulaires ou une usine puis les injecter dans la fonction passée au bloc d'exécution, comme suit:
3 °) Je crois comprendre que dans les vues, dans la plupart des cas, vous avez besoin de ces fonctions d'assistance pour appliquer une sorte de formatage aux chaînes que vous affichez. Ce dont vous avez besoin dans ce dernier cas est d'utiliser des filtres angulaires
Et si vous avez structuré certaines méthodes d'assistance de bas niveau en services angulaires ou en usine, injectez-les simplement dans votre constructeur de filtre:
Et à votre avis:
la source
run
temps. Qu'en est-il du temps de configuration? N'avons-nous pas besoin de services publics?Ai-je bien compris que vous souhaitez simplement définir certaines méthodes utilitaires et les rendre disponibles dans des modèles?
Vous n'êtes pas obligé de les ajouter à chaque contrôleur. Définissez simplement un contrôleur unique pour toutes les méthodes utilitaires et attachez ce contrôleur à <html> ou <body> (en utilisant la directive ngController). Tous les autres contrôleurs que vous attachez n'importe où sous <html> (c'est-à-dire n'importe où, point) ou <body> (n'importe où sauf <head>) hériteront de cette $ scope et auront accès à ces méthodes.
la source
<div class="main-container" ng-controller="UtilController as util">
puis dans toutes les vues intérieures:<button ng-click="util.isNotString(abc)">
Le moyen le plus simple d'ajouter des fonctions utilitaires est de les laisser au niveau global:
Ensuite, le moyen le plus simple d'ajouter une fonction utilitaire (à un contrôleur) est de l'attribuer
$scope
, comme ceci:Ensuite, vous pouvez l'appeler comme ceci:
ou comme ça:
ÉDITER:
La question initiale est de savoir si la meilleure façon d'ajouter une fonction utilitaire consiste à utiliser un service. Je dis non, si la fonction est assez simple (comme l'
isNotString()
exemple fourni par l'OP).L'intérêt d'écrire un service est de le remplacer par un autre (via injection) à des fins de test. Poussé à l'extrême, avez-vous besoin d'injecter chaque fonction utilitaire dans votre contrôleur?
La documentation dit de définir simplement le comportement dans le contrôleur (comme
$scope.double
): http://docs.angularjs.org/guide/controllerla source
Voici une méthode simple, compacte et facile à comprendre que j'utilise.
Tout d'abord, ajoutez un service dans votre js.
Ensuite, dans votre contrôleur, injectez votre objet d'assistance et utilisez n'importe quelle fonction disponible avec quelque chose comme ce qui suit:
la source
Vous pouvez également utiliser le service constant en tant que tel. Définir la fonction en dehors de l'appel constant lui permet également d'être récursive.
la source
Pourquoi ne pas utiliser l'héritage du contrôleur, toutes les méthodes / propriétés définies dans la portée de HeaderCtrl sont accessibles dans le contrôleur à l'intérieur de ng-view. $ scope.servHelper est accessible dans tous vos contrôleurs.
la source