Advertisement
  1. Code
  2. Mobile Development
  3. Ionic Development

Introducción a los componentes de Ionic: Servicios

Scroll to top
Read Time: 18 min
This post is part of a series called Getting Started With Ionic.
Getting Started With Ionic: JavaScript Components

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

1. Introducción a los servicios

En la primera y segunda parte de esta serie sobre Ionic, establecimos el desarrollo local y construimos un par de vistas para cargar una lista de parques utilizando algunos de los componentes de Ionic, como la navegación básica y los componentes de la lista. En este tutorial, profundizaremos en cómo Ionic proporciona una serie de servicios que le permiten administrar la aplicación y la interfaz mediante programación.

Anteriormente, demostramos cómo Ionic proporciona funciones interactivas a través de componentes, que se utilizan como elementos HTML (implementados como directivas angulares). Sin embargo, hay algunos elementos de interfaz que no tienen sentido como componentes creados con HTML, como un cargador o superposiciones de hojas de acción.

Comencemos por echar un vistazo a los servicios que desempeñan los roles en su aplicación. Identifiqué tres tipos principales de servicios en Ionic:    

  • servicios de componentes
  • delegar servicios
  • servicios de asistencia

Servicios de componentes

Los servicios de componentes permiten el uso de componentes, pero en lugar de usar HTML para declararlos (como vimos con ionNavBar) se administran usando JavaScript. En otras palabras, utilizará estos componentes al agregar código a sus controladores. Usaremos dos de estos en el siguiente ejemplo.

Puede ser útil pensar en estos servicios como componentes que tienen un ciclo de vida. Por lo general, desea que se carguen en un punto específico y, una vez finalizados, se eliminan. Por ejemplo, $ionicModal te permite crear un modal. Los modales tienen un ciclo de vida, se abren y cierran por razones específicas. Puede tener un modal que le pida a los usuarios que inicien sesión o pueden cerrar el modelo para omitirlo, completando así el ciclo de vida.

Servicios de delegado

Algunos de los componentes tienen un servicio de delegado complementario que puede modificar o administrar el componente. Es posible que desee manipular mediante programación un componente después de su creación y estos servicios están diseñados para hacerlo posible. Se llaman así porque delegan el comportamiento al componente.

El componente ionNavBar tiene un servicio delegado llamado $ionicNavBarDelegate. Este servicio tiene varios métodos, pero un ejemplo es el método title(), que le permite actualizar el título de la barra de navegación. El alcance de las funciones disponibles para cada servicio de delegado varía, pero deben ser fáciles de detectar en la documentación por el nombre.

Servicios de asistencia

La última categoría son servicios que proporcionan algún tipo de funcionalidad de asistencia o proporcionan información. Solo hay unos pocos y no encajan en las otras dos categorías. Algunos ejemplos son:

  • $ionicPlatform: te ayuda a interactuar con el hardware del dispositivo
  • $ionicGesture: le permite manejar eventos de gestos
  • $ionicPosition: te dice la ubicación de los elementos en la pantalla

Estos servicios de asistencia tienden a ayudarlo a desarrollar la lógica o manejar la interacción. No generan ni modifican componentes por sí mismos.

También veremos algunas otras cosas en este tutorial:   

  • Componentes CSS, que solo son visuales y no brindan ninguna lógica funcional a diferencia de sus hermanos componentes JavaScript
  • Eventos iónicos, que podemos aprovechar para enganchar en eventos, por ejemplo, cuando la vista se está cargando o ha terminado de cargarse
  • más funciones de navegación, que hacen que sea más fácil navegar, administrar el estado y agregar botones a la barra de navegación

Archivos fuente

En este tutorial, vamos a extender la aplicación que comenzamos en el tutorial anterior. Solo un recordatorio, la aplicación está diseñada para proporcionar a los usuarios información sobre sus instalaciones públicas locales, como bibliotecas y parques. La aplicación ya muestra una lista de parques en Chicago y ahora agregaremos la capacidad de mostrar indicadores de carga, ver pantallas de detalles de parques individuales, abrir un menú de acción e implementar algunas funciones básicas para compartir.

Puede ver el proyecto completo en GitHub. El último ejemplo también está disponible para una vista previa.

Puede descargar los archivos o verificarlos usando Git. Una vez que tenga los archivos en su máquina, necesita ejecutar npm install para configurar el proyecto. Si comprueba el código usando Git, puede codificar si restablece el repositorio para que coincida con la última parte que finalizó ejecutando git checkout -b start. Una vez que tenga los archivos, inicie su servidor Ionic ejecutando ionic serve.

2. Implementación de un indicador de carga

Actualmente, la aplicación carga datos y hay un pequeño indicador de círculo del componente de desplazamiento infinito que se muestra hasta que se carga. Sin embargo, en realidad queremos superponer toda la aplicación, por lo que está muy claro que la aplicación se está cargando.

El servicio $ionicLoading es muy útil para superponer y bloquear al usuario para que no interactúe con la aplicación hasta que los datos se hayan cargado. Es configurable Por ejemplo, puede declarar si aparece un icono de carga o algún texto, si desea el fondo o no, o si se debe ocultar automáticamente después de un cierto período de tiempo. Puede ver el cargador en acción en la captura de pantalla a continuación.

Ionic Loader Overlaying the AppIonic Loader Overlaying the AppIonic Loader Overlaying the App

Abra www/views/places.js para hacer algunas modificaciones para usar el cargador. Primero, necesitamos inyectar el servicio en nuestro controlador agregando $ionicLoading a los parámetros de la función. El servicio es bastante simple, solo tiene dos métodos, show() y hide(). Podemos hacer que el cargador se muestre y se oculte llamando a los métodos que se ven aquí en este fragmento.

1
.controller('PlacesController', function($http, $scope, $ionicLoading, Geolocation) {
2
  var vm = this;
3
  var base = 'https://civinfo-apis.herokuapp.com/civic/places?type=park&location=' + Geolocation.geometry.location.lat + ',' + Geolocation.geometry.location.lng;
4
  var token = '';
5
  vm.canLoad = true;
6
  vm.places = [];
7
8
  $ionicLoading.show();
9
10
  vm.load = function load() {
11
    var url = base;
12
    if (token) {
13
      url += '&token=' + token;
14
    }
15
16
    $http.get(url).then(function handleResponse(response) {
17
      vm.places = vm.places.concat(response.data.results);
18
      token = response.data.next_page_token;
19
20
      if (!response.data.next_page_token) {
21
        vm.canLoad = false;
22
      }
23
      $scope.$broadcast('scroll.infiniteScrollComplete');
24
      $ionicLoading.hide();
25
    });
26
  };
27
});

El método $ionicLoading.show() se invoca tan pronto como se carga el controlador, lo que significa que se dispara inmediatamente. Ahora necesitamos decirle al cargador que se oculte después de que los datos hayan terminado de cargarse como lo ve justo después de la $broadcast.

Puede observar que se llama al método $ionicLoading.hide() cada vez que se cargan los datos. Esto no es un problema. Como el cargador ya está oculto, esta llamada no tiene ningún efecto.

Ahora implementamos un servicio iónico. Bastante simple. ¿No? Algunos son un poco más complejos y vamos a trabajar en otro ejemplo utilizando la hoja de acción. Sin embargo, antes de llegar a eso, queremos expandir nuestra aplicación para tener dos vistas tanto para la lista de notas como para ver una nota individualmente.

3. Agregar la vista de nota

Nuestro siguiente paso es crear una nueva vista que muestre más detalles sobre un parque en particular. La información puede variar de un parque a otro, pero nos centraremos en obtener una imagen, sitio web, teléfono e información de dirección. Los resultados de agregar esta vista se muestran aquí.

Place View Showing Park DetailsPlace View Showing Park DetailsPlace View Showing Park Details

Para crear una nueva vista, cree un archivo en www/views/place/place.js e incluya el contenido que ve a continuación. Esta es la definición de controlador y estado para la vista de place.

1
angular.module('App')
2
.config(function($stateProvider) {
3
  $stateProvider.state('place', {
4
    url: '/places/:place_id',
5
    controller: 'PlaceController as vm',
6
    templateUrl: 'views/place/place.html',
7
    resolve: {
8
      Place: function($http, $stateParams) {
9
        var url = 'https://civinfo-apis.herokuapp.com/civic/place?place_id=' + $stateParams.place_id;
10
        return $http.get(url);
11
      }
12
    }
13
  });
14
})
15
.controller('PlaceController', function($scope, Place) {
16
  var vm = this;
17
18
  vm.place = Place.data.result;
19
});

Si echas un vistazo al método config(), ves que estamos declarando un nuevo estado. Este es el ui-router en acción, por lo que debe consultar la documentación de ui-router para obtener todos los detalles sobre la declaración de estados.

La definición del objeto muestra que estamos usando una URL de /places/:place_id Cuando ve una parte de la URL con dos puntos al frente, como por ejemplo: place_id, marca esta parte de la ruta como un parámetro de estado. El estado puede extraer el valor y proporcionárselo utilizando el objeto $stateParams. Por ejemplo, /places/12345 daría como resultado $stateParams.place_id = '12345'.

Ya ha visto las otras partes de la definición anteriormente, a excepción de la propiedad resolve. Esta es una función que le permite solicitar que se llamen varias funciones antes de que se cree el estado. Acepta un objeto de clave y valores de función, por lo que aquí tenemos Place como la clave y se le asignará el resultado de la función.

En la función, puede aceptar parámetros para inyectar, de forma similar a lo que puede hacer con un controlador. Aquí, se inyectan los servicios $http y $stateParams. La función utiliza el valor del place_id pasado a través de la URL y crea y devuelve una solicitud HTTP. Esto es esencialmente lo que se hace en la vista de lugares, excepto que el controlador lo hace.

La función de resolución es lo suficientemente inteligente como para determinar que si devuelve una promesa, esperará a que se resuelva esa promesa antes de crear el estado. En otras palabras, $http.get() devuelve la promesa de cargar los datos y ui-router espera hasta que los datos estén disponibles antes de crear el estado y pasar el Place al controlador. La función de resolución es bastante útil para precargar datos en sus aplicaciones y este es un ejemplo bastante básico de cómo aprovecharla.

Ahora que tenemos el estado definido, el controlador se declara y asigna los datos resultantes de Place (esto es lo que se resolvió en el estado) a vm.place. También necesitamos crear nuestra plantilla para este estado, así que cree un nuevo archivo en www/views/place/place.html y agregue el siguiente contenido a él.

1
<ion-view view-title="{{vm.place.name}}">
2
  <ion-content>
3
    <div class="card" ng-if="vm.place">
4
      <div class="item item-text-wrap item-icon-left">
5
        <i class="icon ion-map"></i> {{vm.place.formatted_address}}</p>
6
      </div>
7
      <div class="item item-image" ng-if="vm.place.photos[0].photo_reference">
8
        <img ng-src="{{'https://civinfo-apis.herokuapp.com/civic/photo?photo_id=' + vm.place.photos[0].photo_reference}}">
9
      </div>
10
      <a ng-if="vm.place.website" class="item item-icon-left" ng-href="{{vm.place.website}}" target="_system">
11
        <i class="icon ion-link"></i> {{vm.place.website}}
12
      </a>
13
      <a ng-if="vm.place.formatted_phone_number" class="item item-icon-left" ng-href="tel://{{vm.place.formatted_phone_number}}">
14
        <i class="icon ion-ios-telephone"></i> {{vm.place.formatted_phone_number}}
15
      </a>
16
    </div>
17
  </ion-content>
18
</ion-view>

Esta plantilla comienza utilizando ionView para envolver el contenido, por lo que el sistema de navegación Ionic puede realizar un seguimiento de la misma correctamente. También asigna un título basado en el nombre del lugar. El contenedor ionContent contiene el contenido principal, y observará que la plantilla utiliza clases CSS en lugar de elementos para crear un componente de tarjeta.

En la parte anterior, hablamos sobre cómo algunos de los componentes son solo clases de CSS. La tarjeta es un ejemplo de eso. Conceptualmente, es como una lista. Los contenidos internos se acumulan verticalmente como una lista, pero el estilo se parece más a una carta. Esto aprovecha los estilos de tarjeta, que incluyen funciones como soporte de imágenes, iconos y otros diseños atractivos que se muestran en la documentación.

Hay unas pocas directivas ngIf utilizadas, ya que no hay garantía de que los datos devueltos tengan un número de teléfono o sitio web. La directiva ngIf se asegura de que no se muestren valores vacíos. También usa ngHref o ngSrc para construir enlaces correctamente.

También notará el uso del protocolo tel://, que, cuando se usa en un teléfono, debe solicitarle al usuario que llame al número cuando lo seleccione. Es una característica práctica que es fácil de usar y se integra muy bien en un dispositivo físico. Algunos programas en su computadora, como Skype, también pueden tratar de hacer una llamada telefónica para usted, dependiendo de su configuración.

Esto debería darnos una vista de trabajo, pero ¿cómo navegamos hacia ella? Tendremos que hacer un par de pequeñas modificaciones para que la navegación funcione desde la vista de lugares.

4. Navegando entre vistas

El ui-router proporciona una directiva ui-sref que se usa para vincular elementos a otro estado. En este caso, queremos que cada uno de los elementos en la lista de la vista de lugares se vincule a la vista de lugar correspondiente.

Abra www/views/places/places.html y agregue la directiva para vincular a cada lugar. Actualice el ionItem con el nuevo atributo aquí.

1
<ion-item ng-repeat="place in vm.places" class="item-avatar" ui-sref="place({place_id: place.place_id})">

La directiva ui-sref tiene un formato donde puede vincular a otro estado por su nombre, no por alguna URL como lo hace con href. Esto es útil ya que las URL pueden cambiar. También puede aceptar parámetros para construir la URL y, en nuestro caso, queremos pasar la propiedad place.place_id. El ui-sref toma propiedades como un objeto, por lo que state-name({param: value}) es la sintaxis.

Ahora haga una vista previa de la aplicación y seleccione un parque, navegará a la nueva vista de lugar place y podrá mirar la barra de direcciones para ver que la URL agrega un valor place_id.  Sin embargo, ahora tenemos un problema. ¿Cómo volvemos a la lista?

Usamos la funcionalidad ionNavBackButton para darnos un botón de retroceso automático. Abra www/index.html y agregue el siguiente fragmento dentro de ionNavBar. Esto agrega un botón de retroceso que solo se mostrará cuando haya un lugar al que regresar.

1
<ion-nav-bar class="bar-balanced">
2
  <ion-nav-back-button class="button-clear">
3
    <i class="ion-arrow-left-c"></i> Back
4
  </ion-nav-back-button>
5
</ion-nav-bar>

La navegación de Ionic es lo suficientemente inteligente como para realizar un seguimiento del historial mientras usa la aplicación. Si hay una vista previa a la que regresar, se mostrará el botón Atrás. De lo contrario, simplemente estará oculto.

También queremos declarar que la vista de lugares nunca debería mostrar el botón Atrás, lo cual podemos hacer agregando la directiva hideBackButton en www/views/places/places.html.

1
<ion-view view-title="Local Parks" hide-back-button="true">

Mientras desarrolla y obtiene una vista previa en el navegador, a veces el historial se restablece. Por ejemplo, cuando está en la vista de lugar y guarda un cambio en su editor, el navegador se recarga automáticamente y restablece el historial. En este caso, el botón Atrás no aparece como se esperaba. Puede solucionar esto volviendo a la lista y actualizando para establecer el historial correctamente.

Hemos progresado mucho, pero ahora, al tocar un elemento en la lista, espera la transición a la nueva vista hasta que la llamada a API regrese con los datos. Puede parecer rápido para usted, pero a veces puede ser lento si la API es lenta. Podría hacer que alguien piense que la aplicación está atascada, lenta o que no registró el toque, ya que no comenzó a reaccionar inmediatamente al toque. Abordamos esto con algunos de los eventos del ciclo de vida que nos ayudan a configurar un cargador para mostrar durante este tiempo.

5. Agregar el cargador durante las transiciones

Para proporcionar una mejor experiencia de usuario, vamos a utilizar el servicio $ionicLoading para superponer la aplicación mientras se cargan los datos para la vista de lugar. Para saber cuándo mostrar y ocultar el cargador, usamos los eventos del ciclo de vida.

Estos eventos se activan en función de eventos de navegación, como antes / después de ingresar a una vista o antes / después de salir de una vista. Puede hacer todo lo que pueda ser necesario en estos momentos, como restablecer algunos datos o tal vez usarlos para enviar información de uso.

Para demostrarlo, agreguemos un detector de eventos a la vista de lugares que maneja la activación del cargador cuando comienza a navegar a la vista de lugares. Abra www/views/places/places.js y agregue lo siguiente al controlador. También debe asegurarse de que $scope esté declarado en los parámetros de la función del controlador para que esté disponible.

1
$scope.$on('$ionicView.beforeLeave', function() {
2
  $ionicLoading.show();
3
});

Este es un detector de eventos de alcance que está escuchando el evento $ionicView.beforeLeave (ver eventos de angular). Ionic transmite este evento a su controlador y llama a la función anónima declarada aquí. Esta función simplemente llama al método $ionicLoading.show() para encender el cargador.

Esto activa el cargador para que aparezca tan pronto como el usuario toque un elemento. Ahora agregamos un fragmento similar a la vista de lugar que maneja la ocultación del cargador cuando la vista ha terminado de cargarse. Abra www/views/place/place.js y agregue lo siguiente al controlador. Debe agregar $ionicLoading y $scope a los parámetros de la función del controlador, ya que no están actualmente inyectados.

1
$scope.$on('$ionicView.afterEnter', function() {
2
  $ionicLoading.hide();
3
});

Esto detecta un evento de alcance diferente que se dispara cuando la vista ha finalizado y llama a la función para ocultar el cargador. El cargador se muestra en el tiempo entre el instante en que el usuario toca un lugar para verlo hasta que la vista se haya cargado por completo. Podrías probar otros eventos y ver cuándo se disparan.

Lo último que hacemos en este tutorial es configurar un botón para compartir hojas de acciones que le permite publicar en Twitter, Facebook o correo electrónico y compartir la información del parque.

6. Botón para compartir usando el servicio Hoja de acciones

Las hojas de acción son bastante útiles para proporcionar una lista de opciones adicionales. La intención suele ser para situaciones en las que desea presentar una lista de acciones que están agrupadas y, en nuestro ejemplo, es una lista de formas de compartir la información del parque. La hoja de acción que crearemos se ve así.

Ionic Action Sheet in ActionIonic Action Sheet in ActionIonic Action Sheet in Action

El servicio de hoja de acciones es un poco más complejo que el servicio de carga, ya que maneja las entradas de configuración y de usuario. Abra www/views/place/place.js y agregue este nuevo método a su controlador. También debe asegurarse de que $ionicActionSheet se inyecte en su controlador.

1
vm.openSheet = function() {
2
  var sheet = $ionicActionSheet.show({
3
    titleText: 'Share this place',
4
    buttons: [
5
      { text: 'Share via Twitter' },
6
      { text: 'Share via Facebook' },
7
      { text: 'Share via Email'}
8
    ],
9
    cancelText: 'Cancel',
10
    buttonClicked: function(index) {
11
      if (index === 0) {
12
        window.open('https://twitter.com/intent/tweet?text=' +
13
          encodeURIComponent('I found this great place! ' + vm.place.url));
14
      } else if (index === 1) {
15
        window.open('https://www.facebook.com/sharer/sharer.php?u=' + vm.place.url);
16
      } else if (index === 2) {
17
        window.open('mailto:?subject=' + encodeURIComponent('I found this great place!') + '&body=' + vm.place.url);
18
      }
19
      sheet();
20
    }
21
  });
22
};

El método openSheet() es responsable de crear la hoja de acción. Hace esto llamando $ionicActionSheet.show (), que devuelve una función que se almacena en la hoja. Eso le permite cerrar la hoja cuando haya terminado con ella más tarde al llamar a sheet(). El método show() toma un objeto con una cantidad de propiedades que analizaremos. Hay varios ejemplos de servicios iónicos que siguen este patrón, como modales y elementos emergentes, por lo que siempre puede manejarlos cerrándolos.

La hoja maneja el título usando la propiedad titleText y se usa generalmente para informar al usuario cómo usar los botones. La propiedad cancelText acepta una cadena que se utiliza para habilitar un botón de cancelar. Si no declara esto, no se seleccionará ningún botón de cancelación. También puede cancelar tocando en el fondo fuera de los botones.

Para declarar los botones, usa la propiedad buttons , que es una matriz de objetos que tienen una propiedad de text. Se muestran en el orden en que están declarados, por lo tanto, ordénelos según corresponda.

La propiedad buttonClicked toma una función y pasa el índice del botón que se seleccionó (como se declaró en los buttons). Por lo tanto, puede averiguar qué hacer en función de qué índice se pase. En esta función, el índice está marcado y abre Facebook, Twitter o usa mailto: para activar el cliente de correo electrónico.

Puede abrir estos enlaces en el Facebook, Twitter o aplicaciones de correo electrónico, dependiendo de la configuración de usuario y tal vez el dispositivo, pero será al menos abrir los enlaces fuera de su aplicación (en un navegador externo). La última pieza es llamar al método sheet(), que cierra la hoja de acción.

La hoja de acción ahora está lista para la acción, pero aún necesitamos agregar un botón para activar la hoja. Para hacer esto, agregamos un botón de la barra de navegación a la vista de lugar que llama a vm.openSheet(). Abra www/views/place/place.html y agregue el fragmento ionNavButtons entre ionView e ionContent.

1
<ion-view view-title="{{vm.place.name}}">
2
  <ion-nav-buttons side="right">
3
    <button class="button button-clear" ng-click="vm.openSheet()">
4
      <i class="icon ion-ios-upload-outline"></i>
5
    </button>
6
  </ion-nav-buttons>
7
  <ion-content>

Aquí hay otra característica útil de navegación iónica que le permite agregar un botón de barra de navegación a una vista particular usando ionNavButtons. Todos los botones internos se agregan a la barra de navegación y puede configurar de qué lado aparecen.

En este punto, todo está funcionando. Los usuarios pueden abrir la hoja de acción para compartir el parque con sus amigos.

Conclusión

En este tutorial, cubrimos los servicios de Ionic y cómo se usan. En el camino, descubrimos una serie de otras características Ionic:

  • Los servicios Ionic se denominan controladores y normalmente tienen un ciclo de vida independiente de la vista actual.
  • El servicio $ionicLoading es útil para mostrar y ocultar un indicador de carga mientras su aplicación carga datos o tiene que bloquear la interfaz de usuario.
  • El servicio $ionicActionSheet presenta al usuario una lista de botones que se superponen a la aplicación para proporcionar un acceso fácil a las acciones importantes.
  • Las funciones de navegación iónic también incluyen el ionNavBackButton para mostrar automáticamente un botón de retroceso cuando es posible retroceder. ionNavButtons le permite agregar botones de la barra de navegación a vistas específicas.
  • Ionic tiene componentes CSS, como la tarjeta, que no tienen características interactivas especiales y se usan solo al declarar clases CSS.

En la próxima entrega, profundizaremos aún más en algunas de las funciones de navegación de Ionic.

Crea una plantilla Ionic y gana $ 1000

Si ya te sientes cómodo con el framework Ionic, entonces quizás quieras considerar participar en el concurso de Envato's Most Wanted para plantillas Ionic. ¿Cómo? Cree una plantilla Ionic única y envíela a Envato Market antes del 27 de abril de 2016.

Las cinco mejores plantillas reciben $ 1000. ¿Interesado? Lea más en el sitio web del concurso para obtener más información sobre los requisitos y las pautas del concurso.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.