Introducción a los componentes de Ionic: JavaScript
Spanish (Español) translation by Elías Nicolás (you can also view the original English article)



En este tutorial, vamos a construir nuestra primera aplicación Ionic juntos y aprender los conceptos básicos de los componentes de JavaScript de Ionic. Estos componentes proporcionan a su aplicación un acceso fácil a las funciones, como barras de navegación y navegación, desplazamiento infinito y listas. Si aún no ha configurado Ionic o necesita actualizar el uso de Ionic CLI, puede revisar el primer tutorial de esta serie.
¿Qué es un componente?
El término componentes es un tanto abusado en el desarrollo de frontend ya que muchos marcos tienen su propia noción que describe un componente. De hecho, Web Components como un estándar oficial de HTML puede complicar aún más el concepto, así que vamos a definir claramente qué es un componente en Ionic.
En un sentido general, un componente es una implementación de un conjunto de características que están encapsuladas por alguna forma de convención de codificación. En otras palabras, puede pensar en un componente como una forma de aislar una característica particular del resto de la aplicación. Puede pensar cómo en HTML hay diferentes tipos de entradas de formulario y cada una de ellas es un tipo de componente que tiene características específicas.
En Ionic, hay dos tipos de componentes, CSS y JavaScript. Los componentes CSS se implementan como un conjunto de clases CSS que modifican un elemento para darle una apariencia específica, como una barra de encabezado.
Los componentes JavaScript se implementan técnicamente como directivas angulares y se usan como elementos HTML en la aplicación. Ofrecen un conjunto de características más completo. Esto generalmente incluye la posibilidad de que los usuarios interactúen con él o con la aplicación para administrar el componente de otro modo. Las pestañas, por ejemplo, permiten que el contenido se muestre u oculte según el usuario que seleccione una pestaña.
En este tutorial nos
enfocaremos en algunos de los componentes de JavaScript. Más adelante en
esta serie, echamos un vistazo más de cerca a los componentes de CSS.
En ocasiones, Ionic implementa un componente como componente CSS y JavaScript, como el componente de pestañas. Esto significa que usted decide cuál usar. Generalmente recomiendo optar por la implementación de JavaScript. En la mayoría de los casos, la sobrecarga de usar el componente de JavaScript es insignificante y creo que hacen que su código sea más fácil de usar.
Archivos fuente
En este tutorial, vamos a crear una aplicación desde cero y continuaremos mejorando la aplicación en el resto de esta serie. La premisa de esta aplicación es crear una aplicación de información cívica que proporcione a los usuarios información sobre sus instalaciones locales, como bibliotecas y parques.
En este tutorial, comenzamos construyendo una aplicación que muestra una lista de parques en Chicago y utiliza desplazamiento infinito para seguir cargando los resultados mientras estén disponibles. Ampliaremos el conjunto de características de la aplicación en los próximos tutoriales.
Creé una API que proporciona la información que necesita la aplicación. La API se basa en las API de Google Maps. Puede ejecutar la API usted mismo, pero requiere obtener una clave API personalizada de Google y las instrucciones se pueden encontrar en el proyecto API. Si hay algún problema al usar la API proporcionada, como que alguien abuse de la API y exceda los límites de uso de la API, ejecutar tu propia versión debería ser útil.
Puede obtener una vista previa de la aplicación en ejecución en Heroku y ver el proyecto completo en GitHub. Sin embargo, te animo a que sigas y crees la aplicación conmigo.
1. Configurando el Proyecto
Primero, necesitas comenzar un nuevo proyecto. Podemos hacer esto ejecutando el siguiente comando:
1 |
ionic start civinfo https://github.com/ionic-in-action/starter |
Esto
descarga un paquete de inicio que incluye una plantilla Ionic vacía
para que podamos comenzar (construido para usar con mi libro Ionic en
acción). Ingrese al directorio, cd civinfo, y ejecute ionic serve.
Ahora puede obtener una vista previa de la carga de una aplicación en blanco en http://localhost:8100 (o en el puerto configurado por Ionic). Recomiendo abrir las herramientas de desarrollador de su navegador para confirmar que vea una pantalla en blanco. Sí, debería ser una pantalla blanca. También sugiero usar la emulación de dispositivo de Chrome mientras previsualiza su aplicación.
2. Configuración de los componentes de navegación de la base
La navegación es tan crucial que deberíamos
comenzar aquí con el diseño de nuestra aplicación. Los principales
componentes de navegación son ionNavBar e ionNavView. La mayoría de las
aplicaciones tienen una característica de diseño
donde hay una barra de navegación con varios títulos y botones de
acción, y luego el resto del área está dedicada al contenido de la vista
actual.
Los componentes ionNavBar e ionNavView proporcionan esa
funcionalidad con cierta inteligencia incorporada para ayudarnos. Nuestra aplicación va a tener varias rutas al final, pero construimos
solo una en este tutorial.
Ionic utiliza UI Router debajo del capó para administrar la navegación y el enrutamiento. Si está familiarizado con él, entonces reconoce la implementación en Ionic. Hay muchos matices, pero lo mantenemos simple en este tutorial. El uso más común y simple es definir cada una de las diversas páginas de su aplicación como un state, que es la forma de enrutador Ionic / UI para definir una vista particular.
Para comenzar, primero incluimos los dos componentes de navegación en www/index.html como ve a continuación, colocándolo dentro del cuerpo.
1 |
<body ng-app="App"> |
2 |
<ion-nav-bar class="bar-balanced"></ion-nav-bar> |
3 |
<ion-nav-view></ion-nav-view>
|
4 |
</body>
|
Una vez que haya agregado el código a index.html, puede volver a cargar la aplicación y debería aparecer una barra verde en la parte superior de la aplicación.



Ha definido el componente ionNavBar, que aparece automáticamente en la parte superior de la pantalla. Más tarde, cuando creamos vistas individuales, esas vistas podrán pasar
un título y botones adicionales para mostrar. Es lo suficientemente
inteligente como para saber qué tan alta debe ser la barra de navegación
para diferentes dispositivos. Esto no es uniforme en todas las
plataformas, por lo que es muy útil. La barra de navegación tiene una
clase de bar-balanced para darle un color verde.
Luego está el
ionNavView, que es el marcador de posición que representa el contenido
para cada una de las vistas. Una vez que definimos una vista, se
renderizará el marcado resultante
aquí y se ajusta automáticamente para ocupar el espacio disponible que
queda después de que se coloca la barra de navegación.
Los componentes de navegación son ejemplos de componentes de JavaScript (también conocidos como directivas angulares). Parecen etiquetas HTML personalizadas y, cuando se usan juntas, son lo suficientemente inteligentes como para mantener la barra de título sincronizada con la vista actual y presentar el contenido correcto según las opciones de navegación del usuario. Para ver esto en acción, sin embargo, necesitamos agregar algunos estados. Comencemos haciendo nuestro primer estado que muestre una lista de parques.
3. Agregar la vista de lista de parques
El objetivo principal de la aplicación es mostrar una lista de recursos cívicos relacionados. Inicialmente, esta será una lista de parques, pero la ampliaremos para incluir otros tipos de recursos, como bibliotecas. Queremos incluir algunas características en esta vista:
- actualizar la barra de navegación con un título
- cargar una lista de parques desde la API
- muestra la lista de elementos en un formato amigable para dispositivos móviles
- Permitir que se carguen más elementos si se llega al fondo, usando desplazamiento infinito
- mostrar una imagen con cada elemento
Paso 1: Configuración de los lugares Estado, controlador y plantilla
Ahora que tenemos algunos objetivos para esta vista, comencemos agregando nuestro archivo JavaScript que registrará esta vista. Cree un nuevo archivo places.js en www/views/places/ y agregue lo siguiente a él:
1 |
angular.module('App') |
2 |
.config(function($stateProvider) { |
3 |
$stateProvider.state('places', { |
4 |
url: '/places', |
5 |
controller: 'PlacesController as vm', |
6 |
templateUrl: 'views/places/places.html' |
7 |
});
|
8 |
})
|
9 |
.controller('PlacesController', function() { |
10 |
});
|
Declaramos un nuevo estado para el enrutador UI utilizando el método $stateProvider.state(). . Esto solo está disponible para ser configurado dentro del método
angular.config() de Angular. Cuando declaras un estado, primero pasas
una cadena para nombrar la ruta, en este caso places. A continuación,
pasa un objeto con varias propiedades que define el estado, como una
URL, un controlador y una plantilla. Puede consultar la documentación
del UI Router para ver todas las opciones de configuración
posibles.
Hemos
declarado un nuevo estado, lo hemos nombrado places, le hemos asignado
una URL de /places, hemos nombrado un controller usando el
controller como sintaxis y hemos enumerado una templateUrl para
cargar. Esta es una definición de estado bastante común y puede ver que
se usa principalmente de la misma manera con otros estados. El
controlador declarado aquí está vacío, pero lo agregaremos pronto.
Esta plantilla es una parte esencial de la vista y describe los aspectos visuales de esa vista. La mayor parte de la lógica y el comportamiento de la vista se gestionarán en el controlador y la plantilla. Nuestro estado declara que queremos cargar un archivo HTML para la plantilla, pero aún no hemos creado uno. Arreglemos eso creando un nuevo archivo places.html en www/views/places/ y añadiendo el código a continuación.
1 |
<ion-view view-title="Local Parks"> |
2 |
<ion-content>
|
3 |
</ion-content>
|
4 |
</ion-view>
|
Hasta ahora en esta plantilla, hemos declarado los componentes ionView y ionContent. El
componente ionView es un contenedor que coloca alrededor de una
plantilla que se debe cargar en el componente ionNavView que declaramos
anteriormente. El atributo de view-title también se usa para pasar
el título que debe mostrar la barra de navegación.
El
componente ionContent es un contenedor de contenido útil, que ayuda a
garantizar que el espacio de contenido tenga el espacio de pantalla
disponible, ayuda a administrar el desplazamiento y puede exponer otros
comportamientos menos comunes. Cuando se carga esta vista, verá que el
título de la barra de navegación aparece como "Local Parks".
Ahora
debemos asegurarnos de que la aplicación carga la secuencia de comandos
para ejecutar agregando places.js a index.html como se ve a
continuación. Recomiendo agregar esto justo antes de la etiqueta </head>.
1 |
<script src="views/places/places.js"></script> |
Puede ver la aplicación, pero aún no verá aparecer la vista. Para ver la vista, vaya a http://localhost:8100/#/places. La URL asignada en la definición de estado se puede usar para navegar a una ruta. Debería aparecer como en la siguiente imagen con el título establecido en "Local Parks".



Esto no es demasiado emocionante todavía, pero representa la vista más básica que probablemente configurará la mayor parte del tiempo. Ahora trabajemos en cargar datos y mostrarlos en la pantalla.
Paso 2: carga de datos
Antes de que podamos hacer mucho más, tenemos que cargar algunos datos. Para hacer esto, necesitamos agregar un servicio angular para ayudarnos a administrar la geolocalización. En un futuro tutorial, el dispositivo detectará la ubicación de un usuario. Hasta entonces, vamos a configurarlo manualmente en Chicago, una de mis ciudades favoritas.
Abra www/js/app.js y agregue el siguiente servicio al
final del archivo. Debe encadenarse con los métodos existentes de
angular.module.
1 |
.factory('Geolocation', function() { |
2 |
return { |
3 |
"formatted_address": "Chicago, IL, USA", |
4 |
"geometry": { |
5 |
"location": { |
6 |
"lat": 41.8781136, |
7 |
"lng": -87.6297982 |
8 |
}
|
9 |
},
|
10 |
"place_id": "ChIJ7cv00DwsDogRAMDACa2m4K8" |
11 |
};
|
12 |
})
|
Este es un servicio angular que devuelve un objeto que coincide con lo que devuelve la API de Google Maps para Chicago. Ahora tenemos detalles de la ubicación para que podamos cargar parques allí.
A continuación, actualizaremos el controlador para cargar la lista
desde la API. Para simplificar, estoy cargando los datos usando el
servicio $http en el controlador. La mejor práctica sería abstraer eso
en un servicio. Abra www/views/places/places.js nuevamente y
actualice el controlador de esta manera:
1 |
.controller('PlacesController', function($http, 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 |
vm.places = []; |
5 |
|
6 |
vm.load = function load() { |
7 |
$http.get(base).then(function handleResponse(response) { |
8 |
vm.places = response.data.results; |
9 |
});
|
10 |
};
|
11 |
|
12 |
vm.load(); |
13 |
});
|
El controlador tiene un método vm.load() para ejecutar la solicitud HTTP y almacena los resultados en vm.places. Cuando guardas esto, debes ver la activación de la solicitud HTTP en las
herramientas de desarrollo de tu navegador. Incluso
si está familiarizado con Angular, es posible que no reconozca este
enfoque exacto para almacenar datos en la variable vm. Recomiendo
revisar la publicación de John Papa sobre por qué este es un enfoque
recomendado si necesita algo de claridad.
Para mostrar los datos, necesitamos actualizar la plantilla también y recorrer la lista de parques para mostrarlos. Abra www/views/places/places.html y actualícelo como se muestra a continuación.
1 |
<ion-view view-title="Local Parks"> |
2 |
<ion-content>
|
3 |
<ion-list>
|
4 |
<ion-item ng-repeat="place in vm.places" class="item-avatar"> |
5 |
<img ng-src="{{place.icon}}" /> |
6 |
<h2>{{place.name}}</h2> |
7 |
<p>{{place.formatted_address}}</p> |
8 |
</ion-item>
|
9 |
</ion-list>
|
10 |
</ion-content>
|
11 |
</ion-view>
|
En la plantilla, estamos utilizando los componentes ionList y ionItem. El
componente ionList es uno de los componentes más útiles porque las
listas son una opción de diseño muy común en dispositivos móviles debido
a pantallas más pequeñas y al uso típico en orientación vertical. Al
igual que una lista que usa ul y li, ionList envuelve cualquier cantidad
de elementos de ionItem.
Las
listas pueden adoptar varias apariencias diferentes y, en este ejemplo,
el elemento de la lista muestra una imagen a la izquierda al declarar
la clase item-avatar en ionItem. El mismo enfoque podría usarse
en una aplicación de mensajería en la que tenga una lista de chats con
un avatar de cada persona.
Dentro del ionItem muestra el nombre y la
dirección. El
estilo predeterminado es truncar automáticamente (usando CSS) cualquier
texto que se desborde para mantener los elementos a la misma altura.



Hemos cargado una lista de parques y los mostramos como una lista usando ionList e ionItem. Podemos dar un paso más y agregar un desplazamiento infinito para
cargar resultados adicionales a medida que el usuario se desplaza cerca
del final de la lista (si están disponibles).
Paso 3: agregar desplazamiento infinito a una lista
Para
hacer que la lista cargue automáticamente elementos adicionales según
el desplazamiento del usuario hacia la parte inferior, podemos utilizar
el componente ionInfiniteScroll. Este
componente se coloca al final de una lista, observa cuando el usuario
se desplazó hasta el final y luego llama a un método que puede cargar
elementos adicionales. También tiene un girador de carga incorporado
para indicar que se están cargando más artículos. La ruleta está oculta
cuando la respuesta se resuelve.
Nuestra API también debe admitir alguna forma de paginación para que esto funcione. En este caso, la API de Google Maps proporciona un token que se debe pasar para cargar el siguiente conjunto de resultados. Necesitamos actualizar el controlador para administrar esta lógica, así que comencemos con la actualización de www/views/places/places.js como se muestra a continuación.
1 |
.controller('PlacesController', function($http, $scope, 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 |
vm.load = function load() { |
9 |
var url = base; |
10 |
if (token) { |
11 |
url += '&token=' + token; |
12 |
}
|
13 |
|
14 |
$http.get(url).then(function handleResponse(response) { |
15 |
vm.places = vm.places.concat(response.data.results); |
16 |
token = response.data.next_page_token; |
17 |
|
18 |
if (!response.data.next_page_token) { |
19 |
vm.canLoad = false; |
20 |
}
|
21 |
$scope.$broadcast('scroll.infiniteScrollComplete'); |
22 |
});
|
23 |
};
|
24 |
});
|
Hemos agregado una nueva propiedad, vm.canLoad, que es un booleano que indica si hay elementos adicionales para cargar. Esto es true por defecto. Hasta que se devuelva una solicitud, no
sabemos si hay elementos adicionales disponibles.
El método vm.load() se
actualiza para agregar el token si está disponible. El controlador de
respuesta ahora concatena los resultados en la matriz. Esto significa
que la segunda página de resultados se agrega después de la primera
página. La API de Google Maps devolverá next_page_token cada vez que
haya más resultados que puedan cargarse. Si esa propiedad falta, podemos
suponer que no hay más elementos para cargar y vm.canLoad se establece
en false. El componente de desplazamiento infinito usa este valor para
determinar cuándo dejar de cargar más elementos.
El cambio final es la
adición de $scope.$broadcast('scroll.infiniteScrollComplete'). El
componente de desplazamiento infinito no tiene conocimiento de cuándo
se completó la solicitud HTTP o exactamente cuándo se guardó para
deshabilitar el símbolo de carga. Por lo tanto, el componente escucha
eventos para actualizarse. En este caso, el evento
scroll.infiniteScrollComplete le dice al
componente que detenga el control numérico y continúe mirando hacia
abajo para que el usuario se desplace.
La última pieza es habilitar esto
en la plantilla. Abra www/views/places/places.html y agregue la
línea entre el final de los componentes ionList y ionContent.
1 |
</ion-item>
|
2 |
</ion-list>
|
3 |
<ion-infinite-scroll on-infinite="vm.load()" ng-if="vm.canLoad"></ion-infinite-scroll> |
4 |
</ion-content>
|
5 |
</ion-view>
|
El componente de desplazamiento infinito ahora está habilitado en su plantilla. Comienza
a observar cuando el componente está visible, que también se activa en
la carga porque no hay lugares visibles y el componente de
desplazamiento infinito está visible. Llama al método declarado en
on-infinite una vez cuando se vuelve
visible (aquí está vm.load()) y espera hasta que se haya disparado el
evento scroll completo.
El ngIf se usa para desactivar el desplazamiento
infinito una vez que la API ha devuelto todos los resultados posibles. En ese caso, desplazarse hacia abajo ya no dispara la carga de más
recursos.
Cuando se usa scroll infinito, es importante usar un ngIf para
deshabilitarlo. Puede ser fácil implementar el componente de tal forma
que el componente intente cargar y cargar y nunca se detenga.
Esto completa la vista de lugares. Mirando hacia atrás, hay un poco de funcionalidad habilitada por 12 líneas de HTML en la plantilla y alrededor de 20 líneas de JavaScript en el controlador.
Resumen
Hemos echado un vistazo a una serie de componentes, que usará con frecuencia en sus aplicaciones iónicas.
- Los componentes Ionic JavaScript se utilizan como elementos HTML y pueden funcionar de forma coordinada.
- Ionic tiene
ionNavVieweionNavBarpara admitir navegación coordinada con diferentes vistas. - Los componentes
ionListyionItemhacen que sea más fácil crear listas amigables para dispositivos móviles. - El componente
ionInfiniteScrollautomáticamente activa una llamada para cargar elementos adicionales y anexarlos a la lista.
El siguiente tutorial analizará algunos de los útiles servicios que proporciona Ionic, como indicadores de carga y elementos emergentes.
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.



