Muestra las diferencias entre dos versiones de la página.
unidades:03_servicios:10_ejemploseguro [2014/07/30 20:29] admin |
unidades:03_servicios:10_ejemploseguro [2014/08/29 22:15] (actual) admin |
||
---|---|---|---|
Línea 1: | Línea 1: | ||
====== 3.10 Ejemplo servicio ====== | ====== 3.10 Ejemplo servicio ====== | ||
- | En este tema retomamos ahora el ejemplo del seguro médico para añadir un ''provider''. | + | En este tema retornamos el ejemplo del seguro médico para añadir un ''provider''. |
- | Al ver el servicio ''$http'' en el tema [[unidades:03_servicios:02_http]] vimos que no debía hacerse una llamada a ''$http'' en el propio controlador . Ahora vamos a crea un ''provider'' que encapsule la llamada a ''$http''. | + | Al ver el servicio ''$http'' en el tema [[unidades:03_servicios:02_http]] vimos que no debía hacerse una llamada a ''$http'' en el propio controlador . Ahora vamos a crear un ''provider'' que encapsule la llamada a ''$http''. |
- | El servicio será un objeto llamado ''remoteResource'' que nos permitirá acceder al servidor para acceder a los datos. Como aun no hemos visto la parte de servidor ni la parte de REST solo vamos a hacer un único método sencillo que nos permita leer los datos, mas adelante en el curso seguiremos mejorando este servicio. | + | El servicio será un objeto llamado ''remoteResource'' que nos permitirá acceder al servidor para acceder a los datos. Como aún no hemos visto la parte de servidor ni la parte de REST ni las promesas , sólo vamos a hacer un único método sencillo que nos permita leer los datos. Más adelante en el curso seguiremos mejorando este servicio. Por lo tanto aun será un poco chapuza el ejemplo. |
- | Nuestro servicio va a ser un ''provider'' ya que tenemos que indicar la | + | ===== La configuración ===== |
+ | |||
+ | Nuestro servicio va a ser un ''provider'' ya que tenemos que indicar la url a partir de la que debemos bajar los datos. Como hemos hecho en el tema anterior éso lo pondremos en una constante de nuestra aplicación. | ||
+ | |||
+ | <sxh js> | ||
+ | app.constant("baseUrl","."); | ||
+ | </sxh> | ||
+ | |||
+ | La constante vale el valor "." porque los datos a bajar están en la misma ruta que nuestra página web. | ||
+ | |||
+ | El provider tendrá un único método para configurarlo llamado ''setBaseUrl'' por lo que tendremos el siguiente bloque config: | ||
+ | <sxh js> | ||
+ | app.config(['baseUrl','remoteResourceProvider',function(baseUrl,remoteResourceProvider){ | ||
+ | remoteResourceProvider.setBaseUrl(baseUrl); | ||
+ | }]); | ||
+ | </sxh> | ||
+ | |||
+ | Fíjate cómo el nombre del provider es "remoteResourceProvider", es decir que acaba en "Provider" aunque nuestro servicio sólo se llama "remoteResource". | ||
+ | |||
+ | ===== El provider ===== | ||
+ | Ahora vamos a definir el provider | ||
+ | <sxh js;highlight: [1,3,6,7,11]> | ||
+ | function RemoteResourceProvider() { | ||
+ | var _baseUrl; | ||
+ | this.setBaseUrl=function(baseUrl) { | ||
+ | _baseUrl=baseUrl; | ||
+ | } | ||
+ | this.$get=['$http',function($http) { | ||
+ | return new RemoteResource($http,_baseUrl); | ||
+ | }]; | ||
+ | } | ||
+ | |||
+ | app.provider("remoteResource",RemoteResourceProvider); | ||
+ | </sxh> | ||
+ | |||
+ | * Línea 1: Definimos el constructor de la clase ''RemoteResourceProvider'' | ||
+ | * Línea 3: Un método público llamado ''setBaseUrl'' para configurar el servicio. Éste es el método que hemos llamado desde el bloque config. | ||
+ | * Línea 6: El método ''$get'', que es el factory-provider con la función de factoría a la que se le inyecta el servicio de ''$http''. | ||
+ | * Línea 7: Ahora la función de factoría crea el nuevo objeto de la clase ''RemoteResource'', siendo esta clase realmente la que hace todo el trabajo y la que se usará desde el controlador. En el constructor además de pasarle el ''$http'' que necesita, también se le pasa la URL Base para configurar el servicio. | ||
+ | * Línea 11: Finalmente se registra el ''provider''. | ||
+ | |||
+ | ===== La clase del propio servicio ===== | ||
+ | Por último nos queda definir la propia clase que implementa el servicio que hemos llamado ''RemoteResource''. | ||
+ | |||
+ | Esta clase tiene un único método llamado ''get''. Este método acepta como parámetros dos funciones de callback . La primera función se llamará si se han podido obtener los datos y tiene como parámetro los datos obtenidos. La segunda función se llamará si ha habido algún error y tiene como parámetros los datos obtenidos y el estado HTTP. | ||
+ | |||
+ | <sxh js;highlight: [1,2,5,7,9]> | ||
+ | function RemoteResource($http,baseUrl) { | ||
+ | this.get=function(fnOK,fnError) { | ||
+ | $http({ | ||
+ | method: 'GET', | ||
+ | url: baseUrl+'/datos.json' | ||
+ | }).success(function(data, status, headers, config) { | ||
+ | fnOK(data); | ||
+ | }).error(function(data, status, headers, config) { | ||
+ | fnError(data,status); | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | </sxh> | ||
+ | * Línea 1: Al constructor de la clase le pasamos el servicio ''$http'' y la URL Base desde la que pedir los datos. | ||
+ | * Línea 2: Es el único método público llamado ''get'' y como ya hemos dicho acepta dos funciones como parámetros. | ||
+ | * Línea 5: La URL que se usará se calcula en función del parámetro ''baseUrl''. | ||
+ | * Línea 7: Si todo va bien y se han podido obtener los datos, se llama a la función de callback llamada ''fnOK'' pasando como argumento los datos obtenidos. | ||
+ | * Línea 9: Si algo ha fallado, se llama a la función de callback llamada ''fnError'' pasando como argumentos los datos obtenidos y el estado HTTP. | ||
+ | |||
+ | ===== El controlador ===== | ||
+ | Por último nos queda ver cómo queda el controlador al usar el nuevo servicio. | ||
+ | |||
+ | <sxh js;highlight: [1,26,27,28,29,30]> | ||
+ | app.controller("SeguroController",['$scope','remoteResource',function($scope,remoteResource) { | ||
+ | $scope.seguro={ | ||
+ | nif:"", | ||
+ | nombre:"", | ||
+ | ape1:"", | ||
+ | edad:undefined, | ||
+ | sexo:"", | ||
+ | casado:false, | ||
+ | numHijos:undefined, | ||
+ | embarazada:false, | ||
+ | coberturas: { | ||
+ | oftalmologia:false, | ||
+ | dental:false, | ||
+ | fecundacionInVitro:false | ||
+ | }, | ||
+ | enfermedades:{ | ||
+ | corazon:false, | ||
+ | estomacal:false, | ||
+ | rinyones:false, | ||
+ | alergia:false, | ||
+ | nombreAlergia:"" | ||
+ | }, | ||
+ | fechaCreacion:new Date() | ||
+ | } | ||
+ | |||
+ | remoteResource.get(function(seguro) { | ||
+ | $scope.seguro=seguro; | ||
+ | },function(data,status) { | ||
+ | alert("Ha fallado la petición. Estado HTTP:"+status); | ||
+ | }); | ||
+ | |||
+ | }]); | ||
+ | </sxh> | ||
+ | |||
+ | * Línea 1: Ahora en el controlador en vez de inyectar el servicio ''$http'' se inyecta el servicio ''remoteResource''. | ||
+ | * Linea 26: Se llama al método ''get'' del servicio ''remoteResource'' y se le pasa como argumentos las 2 funciones. | ||
+ | * Línea 27: Si todo va bien , se pasan los datos a la propiedad ''seguro'' del ''$scope''. | ||
+ | * Línea 28: Es la segunda función anónima que se llama si hay algún error. | ||
+ | * Línea 29: Si falla algo se ejecuta el ''alert''. | ||
+ | ===== Ejemplo ===== | ||
+ | El código completo del ejemplo es el siguiente: | ||
+ | |||
+ | <sxh html;title:index.html> | ||
+ | <!DOCTYPE html> | ||
+ | <html ng-app="app"> | ||
+ | <head> | ||
+ | <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script> | ||
+ | <script src="script.js"></script> | ||
+ | </head> | ||
+ | <body ng-controller="SeguroController"> | ||
+ | <form> | ||
+ | <fieldset> | ||
+ | <legend>Seguro Médico</legend> | ||
+ | <label for="nif">NIF:</label><input id="nif" name="nif" type="text" ng-model="seguro.nif" /><br> | ||
+ | <label for="nombre">Nombre:</label><input id="nombre" name="nombre" type="text" ng-model="seguro.nombre" /><br> | ||
+ | <label for="ape1">1º Apellido:</label><input id="ape1" name="ape1" type="text" ng-model="seguro.ape1" /><br> | ||
+ | <label for="edad">Edad:</label><input id="edad" name="edad" type="text" ng-model="seguro.edad" /><br> | ||
+ | <label for="sexo">Sexo:</label><select id="sexo" name="sexo" type="checkbox" ng-model="seguro.sexo" ><option value="">--Elige opcion--</option><option value="H">Hombre</option><option value="M">Mujer</option></select><br> | ||
+ | <label for="casado">Casado:</label><input id="casado" name="casado" type="checkbox" ng-model="seguro.casado" /><br> | ||
+ | <label for="numHijos">Nº Hijos:</label><input id="numHijos" name="numHijos" type="text" ng-model="seguro.numHijos" /><br> | ||
+ | <label for="embarazada">Embarazada:</label><input id="embarazada" name="embarazada" type="checkbox" ng-model="seguro.embarazada" /><br> | ||
+ | <label for="fechaCreacion">Fecha de creación:</label><input id="fechaCreacion" name="fechaCreacion" type="text" ng-model="seguro.fechaCreacion" /><br> | ||
+ | </fieldset> | ||
+ | <fieldset> | ||
+ | <legend>Coberturas</legend> | ||
+ | <label for="oftalmologia">Oftalmologia:</label><input id="oftalmologia" name="oftalmologia" type="checkbox" ng-model="seguro.coberturas.oftalmologia" /><br> | ||
+ | <label for="dental">Dental:</label><input id="dental" name="dental" type="checkbox" ng-model="seguro.coberturas.dental" /><br> | ||
+ | <label ng-show="seguro.sexo==='M'" for="fecundacionInVitro">Fecundacion In Vitro:</label><input ng-show="seguro.sexo==='M'" id="fecundacionInVitro" name="fecundacionInVitro" type="checkbox" ng-model="seguro.coberturas.fecundacionInVitro" /><br> | ||
+ | </fieldset> | ||
+ | <fieldset> | ||
+ | <legend>Enfermedades</legend> | ||
+ | <label for="corazon">Corazon:</label><input id="corazon" name="corazon" type="checkbox" ng-model="seguro.enfermedades.corazon" /><br> | ||
+ | <label for="estomacal">Estomacal:</label><input id="estomacal" name="estomacal" type="checkbox" ng-model="seguro.enfermedades.estomacal" /><br> | ||
+ | <label for="rinyones">Riñones:</label><input id="rinyones" name="rinyones" type="checkbox" ng-model="seguro.enfermedades.rinyones" /><br> | ||
+ | <label for="alergia">Alergia:</label><input id="alergia" name="alergia" type="checkbox" ng-model="seguro.enfermedades.alergia" /><br> | ||
+ | <label for="nombreAlergia">Nombre de la alergia:</label><input ng-disabled="seguro.enfermedades.alergia===false" id="nombreAlergia" name="nombreAlergia" type="text" ng-model="seguro.enfermedades.nombreAlergia" /><br> | ||
+ | </fieldset> | ||
+ | </form> | ||
+ | </body> | ||
+ | </html> | ||
+ | </sxh> | ||
+ | |||
+ | <sxh js;title:script.js> | ||
+ | var app = angular.module("app", []); | ||
+ | |||
+ | function RemoteResource($http,baseUrl) { | ||
+ | this.get=function(fnOK,fnError) { | ||
+ | $http({ | ||
+ | method: 'GET', | ||
+ | url: baseUrl+'/datos.json' | ||
+ | }).success(function(data, status, headers, config) { | ||
+ | fnOK(data); | ||
+ | }).error(function(data, status, headers, config) { | ||
+ | fnError(data,status); | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function RemoteResourceProvider() { | ||
+ | var _baseUrl; | ||
+ | this.setBaseUrl=function(baseUrl) { | ||
+ | _baseUrl=baseUrl; | ||
+ | } | ||
+ | this.$get=['$http',function($http) { | ||
+ | return new RemoteResource($http,_baseUrl); | ||
+ | }]; | ||
+ | } | ||
+ | |||
+ | app.provider("remoteResource",RemoteResourceProvider); | ||
+ | |||
+ | |||
+ | |||
+ | app.constant("baseUrl", "."); | ||
+ | app.config(['baseUrl', 'remoteResourceProvider',function(baseUrl, remoteResourceProvider) { | ||
+ | remoteResourceProvider.setBaseUrl(baseUrl); | ||
+ | }]); | ||
+ | |||
+ | |||
+ | app.controller("SeguroController", ['$scope', 'remoteResource',function($scope, remoteResource) { | ||
+ | $scope.seguro = { | ||
+ | nif: "", | ||
+ | nombre: "", | ||
+ | ape1: "", | ||
+ | edad: undefined, | ||
+ | sexo: "", | ||
+ | casado: false, | ||
+ | numHijos: undefined, | ||
+ | embarazada: false, | ||
+ | coberturas: { | ||
+ | oftalmologia: false, | ||
+ | dental: false, | ||
+ | fecundacionInVitro: false | ||
+ | }, | ||
+ | enfermedades: { | ||
+ | corazon: false, | ||
+ | estomacal: false, | ||
+ | rinyones: false, | ||
+ | alergia: false, | ||
+ | nombreAlergia: "" | ||
+ | }, | ||
+ | fechaCreacion: new Date() | ||
+ | } | ||
+ | |||
+ | remoteResource.get(function(seguro) { | ||
+ | $scope.seguro = seguro; | ||
+ | }, function(data, status) { | ||
+ | alert("Ha fallado la petición. Estado HTTP:" + status); | ||
+ | }); | ||
+ | |||
+ | } | ||
+ | ]); | ||
+ | </sxh> | ||
+ | |||
+ | {{url>http://embed.plnkr.co/pmsJkq}} | ||
+ | ===== Malas prácticas ===== | ||
+ | En muchos ejemplos que se ven de AngularJS se tiende a definir un provider en un único bloque en vez de definir diversas funciones separadas como hemos hecho aqui. | ||
+ | |||
+ | Podemos ver el siguiente trazo de código en el que se ha definido el provider usando varias funciones anónimas anidadas. | ||
+ | |||
+ | <sxh js> | ||
+ | app.provider("remoteResource", function() { | ||
+ | var _baseUrl; | ||
+ | this.setBaseUrl = function(baseUrl) { | ||
+ | _baseUrl = baseUrl; | ||
+ | } | ||
+ | this.$get = ['$http', | ||
+ | function($http) { | ||
+ | return new function($http, baseUrl) { | ||
+ | this.get = function(fnOK, fnError) { | ||
+ | $http({ | ||
+ | method: 'GET', | ||
+ | url: baseUrl + '/datos.json' | ||
+ | }).success(function(data, status, headers, config) { | ||
+ | fnOK(data); | ||
+ | }).error(function(data, status, headers, config) { | ||
+ | fnError(data, status); | ||
+ | }); | ||
+ | } | ||
+ | }($http, _baseUrl); | ||
+ | } | ||
+ | ]; | ||
+ | }); | ||
+ | </sxh> | ||
+ | |||
+ | Este código - aunque funciona - no es recomendable por lo complejo que resulta de entender. | ||
+ | |||
+ | ===== Referencias ===== | ||
+ | * [[https://github.com/johnpapa/angularjs-styleguide/blob/master/README.md|AngularJS Style Guide by @john_papa]] | ||
+ | * [[https://github.com/toddmotto/angularjs-styleguide/blob/master/README.md|AngularJS styleguide by @toddmotto]] |