Veremos cómo reaccionar a los cambios de rutas, mostrando otras vistas de la aplicación, apoyados por el componente iron-pages.
El sistema de routing no tendría mucho sentido en una aplicación que no fuera capaz de reconocer las rutas y automáticamente cambiar la vista o pantalla de la app. En este artículo nos vamos a preocupar por la parte del intercambio de vistas, que realmente es muy sencillo de realizar.
Recuerda que este es el segundo artículo en el que trabajamos el sistema de routing de Polymer, por lo que, si no lo has hecho, te vendría bien antes leer el artículo de Componentes del sistema de routing de Polymer.
Para realizar esta parte nos apoyaremos en un componente de Polymer muy utilizado que se llama "iron-pages". Este componente es el que nos permite de una manera cómoda realizar el intercambio de vistas, también de manera declarativa. Vamos a conocer conociendo más de cerca este componente.
Componente iron-pages
El componente de Polymer iron-pages es básicamente un intercambiador de vistas. De entre varias páginas, vistas o elementos, nos permite mostrar una de ellas.
Para usar este componente lo tendrás que instalar:
bower install --save PolymerElements/iron-pages
Y por supuesto, hacer el correspondiente import.
<link rel="import" href="./bower_components/iron-pages/iron-pages.html">
Para usarlo necesitamos el propio componente iron-pages junto con las vistas que debe intercambiar.
<iron-pages selected="0">
<section>cero</section>
<section>uno</section>
<section>dos</section>
</iron-pages>
En este componente hemos definido tres vistas. Las tres vistas aquí las hemos indicado con etiquetas SECTION, pero podríamos haber usado cualquier otra etiqueta. Incluso podrían ser custom elements. Simplemente tienes que colocar todas las vistas que quieras, con cualquier elemento que sea hijo directo de iron-pages.
Apreciarás el atributo "selected", que indica cuál de las vistas es la que se debe presentar al usuario. Al indicar selected="0" estamos forzando para que se vea la primera vista, el primer elemento hijo de iron-pages, por lo que aparecería la palabra "cero" que es el contenido del primer elemento.
Sin embargo, para que realmente tenga más usabilidad el componente iron-pages, no se suele usar un atributo numérico para indicar la vista a mostrar, sino una cadena (Así es más fácil de recordar qué es lo que se debe mostrar y si se reordenan los elementos dentro del iron-pages no alteraría el índice de cada vista).
Para indicar qué cadena corresponderá a cada elemento se usa un atributo arbitrario en el componente y se indica el nombre de ese atributo por medio de la propiedad attrForSelected del iron-pages. Producirá un código como este:
<iron-pages selected="[[nombreDePagina]]" attr-for-selected="page">
<div page="productos"></div>
<div page="mi-cuenta"></div>
<div page="contacto"></div>
</iron-pages>
Aquí hemos incorporado un binding a la propiedad "selected" y un valor en attrForSelected. El atributo definido en attrForSelected ("page") es el que se usa en los componentes para definir qué es lo que se debe mostrar. Ahora en "nombreDePagina" tendremos un valor como "productos", "mi-cuenta" o "contacto", lo que resulta mucho más útil que un valor numérico.
Usar los valores de una ruta para mostrar la vista adecuada
Con lo que has visto de iron-pages y lo que ya sabes del sistema de routing creo que es sencillo entender cómo vamos a usar ambos sistemas en conjunto para usar las rutas de aplicación.
Recuerda que tenemos un componente app-route que nos expone un objeto "data" donde se encuentran descompuestos los valores de un patrón de URL.
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{data}}"
tail="{{tail}}">
</app-route>
Ahora con data.page, que contiene el nombre de la página que se está visitando, somos capaces de alimentar el iron-pages para que automáticamente muestre la vista que debe.
<iron-pages selected="[[data.page]]" attr-for-selected="page">
<div page="productos"></div>
<div page="mi-cuenta"></div>
<div page="contacto"></div>
</iron-pages>
Navegación
Podemos ahora, para completara este ejemplo, colocar un navegador para cambiar de secciones en nuestro sitio web. Aunque usaremos un NAV, podría ser una etiqueta cualquiera. Simplemente necesitamos los enlaces para que, de manera natural, el navegador nos lleve a otras direcciones, bajo las que se presentarán otras vistas.
<nav>
<a href="/productos/">Productos</a>
<a href="/mi-cuenta/">Mi cuenta</a>
<a href="/contacto/">Contacto</a>
</nav>
A fin de despejar posibles dudas vamos a repasar un poco el flujo de ejecución provocado por la navegación entre secciones:
- El usuario pulsa sobre un enlace del navegador.
- De manera natural, el navegador viaja a la nueva URL.
- Nuestro componente app-location recibe el cambio de la URL que se está visualizando y lo envía al objeto "route".
- El componente app-route recibe el cambio del objeto "route", gracias al sistema de binding de Polymer.
- El componente app-route cambia el valor de data.page.
- El componente iron-pages se entera del cambio de data.page, alterando la vista que debe ser mostrada en la web.
Custom elements como páginas
Otra cosa que ya hemos mencionado, pero queremos dejar bien clara, es que podemos usar nuestros propios componentes como vistas en el iron-pages. De hecho es algo bastante común que las vistas que se desean intercambiar estén en componentes independientes.
Nuestro iron-pages quedaría entonces como esto:
<iron-pages selected="[[data.page]]" attr-for-selected="page">
<productos-page page="productos"></productos-page>
<mi-cuenta-page page="mi-cuenta"></mi-cuenta-page>
<contacto-page page="contacto"></contacto-page>
</iron-pages>
Como ves, en vez de tener elementos DIV, SECTION o cualquier otro (que no indica nada en concreto), podemos tener custom element para cada ruta interna. Esos componentes podrán a su vez tener su template con el código HTML que se debe poner en cada sección.
Ejemplo completo de navegación por secciones y rutas de aplicación
Para acabar vamos a colocar ahora el código completo de nuestro componente:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../bower_components/app-route/app-location.html">
<link rel="import" href="../bower_components/app-route/app-route.html">
<link rel="import" href="pages/productos-page.html">
<link rel="import" href="pages/mi-cuenta-page.html">
<link rel="import" href="pages/contacto-page.html">
<dom-module id="link-app">
<template>
<style>
:host {
display: block;
}
</style>
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{data}}"
tail="{{tail}}">
</app-route>
<nav>
<a href="/productos/">Productos</a>
<a href="/mi-cuenta/">Mi cuenta</a>
<a href="/contacto/">Contacto</a>
</nav>
<iron-pages selected="[[data.page]]" attr-for-selected="page">
<productos-page page="productos"></productos-page>
<mi-cuenta-page page="mi-cuenta"></mi-cuenta-page>
<contacto-page page="contacto"></contacto-page>
</iron-pages>
<p>
[[data.page]]
</p>
</template>
<script>
Polymer({
is: 'link-app'
});
</script>
</dom-module>
Eso es todo por ahora. Seguiremos en la próxima entrega de nuestro Manual de Polymer.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...