Me gustaría agregar algunas funciones de utilidad a mi aplicación AngularJS. Por ejemplo:
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
¿Es la mejor manera de hacer esto para agregarlos como un servicio? De lo que he leído, puedo hacer esto, pero luego me gustaría usarlos en mis páginas HTML, ¿es posible que estén en un servicio? Por ejemplo, ¿puedo usar lo siguiente?
<button data-ng-click="doSomething()"
data-ng-disabled="isNotString(abc)">Do Something
</button>
¿Puede alguien darme un ejemplo de cómo podría agregar estos? ¿Debo crear un servicio o hay alguna otra forma de hacerlo? Lo más importante es que me gustaría que estas funciones de utilidad en un archivo y no se combinen con otra parte de la configuración principal.
Entiendo que hay algunas soluciones, pero ninguna de ellas es tan clara.
Solución 1 - Propuesta por Urban
$scope.doSomething = ServiceName.functionName;
El problema aquí es que tengo 20 funciones y diez controladores. Si hiciera esto, significaría agregar mucho código a cada controlador.
Solución 2 : propuesta por mí
var factory = {
Setup: function ($scope) {
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
La desventaja de esto es que, al comienzo de cada controlador, tendría una o más de estas llamadas de Configuración a cada servicio que pasó el alcance de $.
Solución 3 - Propuesta por Urban
La solución propuesta por urban de crear un servicio genérico se ve bien. Aquí está mi configuración 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);
¿Debo agregar el servicio genérico a esto y cómo podría hacerlo?
Respuestas:
EDITAR 7/1/15:
Escribí esta respuesta hace bastante tiempo y no he estado siguiendo mucho con angular durante un tiempo, pero parece que esta respuesta sigue siendo relativamente popular, por lo que quería señalar que un par de puntos @nicolas Las marcas a continuación son buenas. Por un lado, inyectar $ rootScope y adjuntar los ayudantes allí evitará que tenga que agregarlos para cada controlador. Además, estoy de acuerdo en que si lo que está agregando debe considerarse como servicios O filtros angulares, deben adoptarse en el código de esa manera.
Además, a partir de la versión actual 1.4.2, Angular expone una API "Proveedor", que se puede inyectar en bloques de configuración. Vea estos recursos para más:
https://docs.angularjs.org/guide/module#module-loading-dependencies
Inyección de valor de dependencia AngularJS dentro de module.config
No creo que vaya a actualizar los bloques de código reales a continuación, porque en estos días no estoy usando activamente Angular y realmente no quiero arriesgarme a una nueva respuesta sin sentirme cómodo de que realmente se ajuste a lo mejor prácticas Si alguien más se siente a gusto, anímate.
EDITAR 2/3/14:
Después de pensar en esto y leer algunas de las otras respuestas, creo que prefiero una variación del método presentado por @Brent Washburne y @Amogh Talpallikar. Especialmente si está buscando utilidades como isNotString () o similar. Una de las ventajas claras aquí es que puede reutilizarlos fuera de su código angular y puede usarlos dentro de su función de configuración (que no puede hacer con los servicios).
Dicho esto, si está buscando una forma genérica de reutilizar lo que deberían ser servicios, la respuesta anterior creo que sigue siendo buena.
Lo que haría ahora es:
app.js:
controller.js:
Luego, en su parcial, puede usar:
Antigua respuesta a continuación:
Sería mejor incluirlos como un servicio. Si va a reutilizarlos en varios controladores, incluirlos como servicio evitará que tenga que repetir el código.
Si desea utilizar las funciones de servicio en su html parcial, debe agregarlas al alcance de ese controlador:
$scope.doSomething = ServiceName.functionName;
Luego, en su parcial, puede usar:
Aquí hay una manera de mantener todo esto organizado y libre de demasiadas molestias:
Separe su controlador, servicio y código / configuración de enrutamiento en tres archivos: controllers.js, services.js y app.js. El módulo de la capa superior es "app", que tiene las dependencias app.controllers y app.services como dependencias. Entonces app.controllers y app.services pueden declararse como módulos en sus propios archivos. Esta estructura organizativa se acaba de tomar de Angular Seed :
app.js:
services.js:
controller.js:
Luego, en su parcial, puede usar:
De esa manera, solo agrega una línea de código a cada controlador y puede acceder a cualquiera de las funciones de los servicios donde sea que ese alcance sea accesible.
fuente
Al llegar a este viejo hilo, quería enfatizar que
1 °) las funciones de utilidad pueden (¿deberían?) Agregarse al rootcope a través de module.run. No es necesario instanciar un controlador de nivel raíz específico para este propósito.
2 °) Si organiza su código en módulos separados, debe usar servicios angulares o de fábrica y luego inyectarlos en la función pasada al bloque de ejecución, de la siguiente manera:
3 °) Entiendo que en las vistas, para la mayoría de los casos, necesita estas funciones auxiliares para aplicar algún tipo de formato a las cadenas que muestra. Lo que necesita en este último caso es usar filtros angulares
Y si ha estructurado algunos métodos auxiliares de bajo nivel en servicios angulares o de fábrica, simplemente inyéctelos dentro de su constructor de filtros:
Y en tu opinión:
fuente
run
tiempo. ¿Qué pasa con el tiempo de configuración? ¿No necesitamos utilidades por ahí?¿Entiendo correctamente que solo desea definir algunos métodos de utilidad y ponerlos a disposición en plantillas?
No tiene que agregarlos a cada controlador. Simplemente defina un solo controlador para todos los métodos de utilidad y adjunte ese controlador a <html> o <body> (usando la directiva ngController). Cualquier otro controlador que adjunte en cualquier lugar bajo <html> (es decir, en cualquier lugar, punto) o <body> (en cualquier lugar menos <head>) heredará ese $ scope y tendrá acceso a esos métodos.
fuente
<div class="main-container" ng-controller="UtilController as util">
luego, en cualquier vista interior:<button ng-click="util.isNotString(abc)">
La forma más fácil de agregar funciones de utilidad es dejarlas a nivel global:
Entonces, la forma más simple de agregar una función de utilidad (a un controlador) es asignarla de
$scope
esta manera:Entonces puedes llamarlo así:
o así:
EDITAR:
La pregunta original es si la mejor manera de agregar una función de utilidad es a través de un servicio. Digo no, si la función es lo suficientemente simple (como el
isNotString()
ejemplo proporcionado por el OP).El beneficio de escribir un servicio es reemplazarlo con otro (mediante inyección) con el propósito de probarlo. Llevado al extremo, ¿necesita inyectar cada función de utilidad en su controlador?
La documentación dice simplemente definir el comportamiento en el controlador (como
$scope.double
): http://docs.angularjs.org/guide/controllerfuente
Aquí hay un método simple, compacto y fácil de entender que uso.
Primero, agregue un servicio en su js.
Luego, en su controlador, inyecte su objeto auxiliar y use cualquier función disponible con algo como lo siguiente:
fuente
También puede usar el servicio constante como tal. La definición de la función fuera de la llamada constante también permite que sea recursiva.
fuente
¿Por qué no utilizar la herencia del controlador? Todos los métodos / propiedades definidos en el alcance de HeaderCtrl son accesibles en el controlador dentro de ng-view. $ scope.servHelper es accesible en todos sus controladores.
fuente