Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Manual de
Polymer
En este manual vamos a explicar cómo trabajar con Polymer, una librería para el desarrollo sencillo y rápido de sitios web,
basada sobre el estándar de los Web Components. Básicamente dentro de Polymer puedes encontrar dos cosas:
1) Por un lado te ofrece un catálogo de elementos, mediante los que puedes enriquecer el HTML con nuevas etiquetas
capaces de hacer diversas cosas útiles. Esas nuevas etiquetas es lo que se conoce como Custom Elements y que
cualquier persona podría usar en cualquier proyecto, incluso sin tener que meterse con asuntos relacionados con la
programación.
2) Ya para el que sepa programar y que quiera invertir tiempo en aprender esta librería, Polymer ofrece una manera muy
rápida y sencilla de registrar componentes y facilitar la comunicación entre ellos y la interoperabilidad, a través de binding
desarrolloweb.com/manuales/polymer.html Página 1
Manual de Polymer
http://www.desarrolloweb.com
15 artículos publicados
Aviso: Puedes imprimir este manual, siempre que contenga este aviso, respetes el encabezado y pie del PDF, así
como mantengas la información de los autores originales.
Los manuales de DesarrolloWeb.com tienen © copyright de sus autores. Por favor, consulta autorización para su
distribución en otros medios.
desarrolloweb.com/manuales/polymer.html Página 2
Manual de Polymer
Parte 1:
Introducción a Polymer
Google es el creador de Polymer. Como prueba del intenso apoyo a esta librería se
puede señalar que actualmente es su principal opción para el desarrollo de proyectos
internos.
Comenzaremos con una serie de artículos básicos enfocados en el uso de Polymer y de
sus elementos del catálogo, para demostrar su utilidad y las impactantes cosas que
podemos hacer sin necesidad de poseer grandes conocimientos de esta librería.
1.1.- Polymer
Polymer es una potente librería para desarrollo de sitios web del lado del cliente, basada en los
estándares de los Web Components.
Polimer es una librería para realizar Web Components de una manera más rápida y productiva, que además contiene un
amplio catálogo de elementos disponibles para basar el desarrollo de nuevos componentes.
A lo largo de este artículo te ofrecemos una introducción general a esta estupenda herramienta para el desarrollo de
sitios web. En futuros artículos del Manual de Polymer completaremos esta información, para hablar sobre cómo usar los
componentes que nos ofrece Polymer y por supuesto, cómo crear nuestros propios Custom Elements.
Además, en el presente texto trataremos de contestar a las preguntas típicas que cualquier persona se hace cuando oye
hablar de Polymer ¿cómo encaja Polymer en el panorama actual del desarrollo del lado del cliente? o incluso ¿compite
con AngularJS o ReacJS+Flux?
desarrolloweb.com/manuales/polymer.html Página 3
Manual de Polymer
Recientemente fue lanzada la versión 1.0 de Polymer, ya recomandada para usar en producción. El propio Google,
creador de la librería la está usando en diversos proyectos populares. Hace pocos días se presentó Polymer 1.2, lo que
nos indica que la herramienta está suficientemente madura como para poder usarla en cualquier tipo de proyecto y
beneficiarnos ya de las ventajas del desarrollo basado en Web Components, pero además de una manera rápida, sencilla
y llena de utilidades que nos faciliten la vida como programadores frontend.
Los propios creadores de Polymer se esfuerzan en insistir en el hecho de estar en frente de una librería y no un
framework. Polymer no es MVC, como lo podría ser AngularJS o EmberJS. Tampoco hace uso de una arquitectura definida,
que debas seguir para el desarrollo de una aplicación completa, pues se ciñe únicamente a la arquitectura para crear
componentes aislados que se puedan distribuir, reutilizar y combinar entre sí (es la definición general de los web
components).
Por poner un ejemplo, AngularJS (en su versión 1.x) incluye las directivas, que nos permiten extender el HTML para crear
tags enriquecidos que son capaces de hacer cosas diversas. Para quien no conoce las directivas de Angular, éstas
permiten especializar etiquetas, aportando comportamientos diversos. Esas directivas están construidas en base a código
propio de AngularJS, mientras que Polymer, que hace algo similar, está construido en base a las herramientas existentes
dentro del Javascript de los navegadores modernos.
desarrolloweb.com/manuales/polymer.html Página 4
Manual de Polymer
Lo que debe quedar claro es que Polymer se diferencia, con respecto a AngularJS o ReactJS, por estar construido encima
de las especificaciones de los Web Components. Por ello no son librerías comparables y, gracias a basarse en estándares
de la W3C, se podría suponer una vida más larga a Polymer que a otras alternativas para el desarrollo de interfaces de
usuario y aplicaciones web.
Un completo sistema de Polyfills, que permiten dar soporte al estándar de Web Components a navegadores que no
lo han implementado todavía de manera nativa.
Un kit de herramientas destinadas a que cualquier desarrollador pueda crear sus propios componentes.
Una enorme librería de elementos clasificados en varias áreas, en los cuales podremos basarnos para hacer
nuevos componentes que den vida a páginas web y aplicaciones para móviles.
A lo largo de futuros artículos vamos a explicar cada uno de esos item, viendo ejemplos concretos con los que aprender a
usar Polymer.
Desarrollo declarativo
Lo interesante de los web components y Polymer es que te permite hacer lo que se conoce como "desarrollo declarativo".
En vez de crear tus comportamientos escribiendo código Javascript que realice las cosas que necesitas, vamos a
comenzar a desarrollar en base a la declaración de elementos con etiquetas HTML nuevas que realicen las tareas que
necesitas.
O sea, para agregar un icono no necesitas tener una imagen, asociada a una URL en el atributo src. Puedes
implementarlo por medio de un Custom element, que viene a ser como una nueva etiqueta del HTML. Por ejemplo:
<iron-icon icon="icons:alarm"></iron-icon>
Pero un icono es un componente muy sencillo, quizás la diferencia entre usar una etiqueta IMG y este custom element es
bien poca. Pero piensa por ejemplo en un panel lateral, que se colapsa automáticamente en pantallas de dimensiones
pequeñas y que podemos desplegar para ver su contenido.
<paper-drawer-panel>
<div drawer> Panel lateral </div>
<div main> Panel del cuerpo </div></paper-drawer-panel>
Si para hacer una conexión Ajax antes tenías que escribir un bloque entero de Javascript, con Polymer podrás escribirlo
con un Custom Element:
<iron-ajax url$="https://restcountries.eu/rest/v1/name/spain"></iron-ajax>
Todos estos elementos te los regala Polymer, pero además te ofrece el kit de herramientas para que puedas crear
cualquier otro componente que te puedas imaginar, desde cero o basándote en componentes creados por el propio
equipo de Polymer, o cualquier persona que los haya publicado para la comunidad. Una vez creas tu propio elemento,
podrás usalo miles de veces sin tener que escribir una línea de Javascript.
En este artículo no vamos a entrar en código de ejemplos, pero ya os podemos adelantar una imagen de componentes
que estamos preparando para la realización del Manual de Polymer, en el que se demuestra comparativamente la
diferencia entre escribir el código de custom elements con Javascript nativo y usando Polymer. Podrás apreciar que el
código de Polymer es sensiblemente menor y menos complejo, lo que permite no solo un desarrollo más rápido, sino
también un mantenimiento más sencillo.
desarrolloweb.com/manuales/polymer.html Página 5
Manual de Polymer
Catálogo de elementos
Si estás interesado en Polymer lo más recomendable es que comiences explorando el catálogo de elementos, para darte
cuenta de las cosas que se pueden hacer y de la potencia de esta librería.
desarrolloweb.com/manuales/polymer.html Página 6
Manual de Polymer
móviles. Como por ejemplo, poder trabajar offline y poder operar con la página aunque no se tenga conexión, trabajo con
notificaciones, etc.
Mo: Molecules
Son envoltorios de librerías de terceros, para usar mediante la arquitectura de los componentes web.
Conclusión
Con respecto a las tecnologías para la web, y en el caso concreto de las librerías Javascript para el desarrollo frontend, es
común marearse con tantos proyectos y alternativas para hacer las mismas cosas. Pero Polymer es diferente porque se
basa en los estándares.
La verdad es que, cuando te aproximas a Polymer, es fácil sentirse emocionado con este nuevo estilo de programación,
basado en componentes reutilizables. Muchas tareas que haces repetitivamente en proyectos y que por unas u otras
situaciones resulta complicado reutilizar, con Polymer te asegura desarrollarlas una vez y utilizarlas en cualquier número
de proyectos. Pero además podrás usarlas sin tener que escribir una línea de Javascript.
Otra garantía que nos ofrece Polymer es que está apoyado fuertemente por Google, lo que nos indica que tiene mucho
margen para crecimiento. En futuros artículos seguiremos explicando Polymer y cómo realizar el desarrollo de nuestros
propios componentes con esta impactante librería para el desarrollo frontend.
Si te ha interesado esta tecnología, el siguiente paso consiste en aprender a usar los componentes de Polymer, para lo
que no necesitas ningún conocimiento de la propia librería ni de programación.
desarrolloweb.com/manuales/polymer.html Página 7
Manual de Polymer
Si tienes 10 minutos y quieres ver una explicación en vídeo de lo que es Polymer te recomendamos ver el siguiente vídeo
que es el primero de una serie de videotutoriales de Polymer.
En este artículo vamos a hacer una primera aproximación a Polymer desde el lado del programador. En resumen
queremos mostrar cuáles serían los primeros pasos para obtener Polymer y explicar unas primeras nociones sobre cómo
se podría organizar la estructura de carpetas en un proyecto donde pretendamos usar esta librería.
Además, al final del texto encontrarás un vídeo donde podrás ver todo el proceso paso por paso, realizando además un
ejemplo de componente para comenzar. Si tienes 15 minutos y prefieres verlo en el videotutorial, salta todo este texto y
vete al final del artículo.
Así que no seremos nosotros los que descarguemos la librería, sino que lo realizaremos mediante Bower.
Nota: Si no conoces Bower es el momento de leerte el artículo de introducción a Bower. Hay más artículos de Bower
en DesarrolloWeb, pero con que te leas el primero es suficiente.
Puedes partir de una carpeta vacía. Entonces te situas dentro de esa carpeta con el terminal. A partir de ahí instalaremos
Polymer.
El primer paso recomendado es iniciar el proyecto con Bower. Como sabes esto nos creará el bower.json con la
información del proyecto.
desarrolloweb.com/manuales/polymer.html Página 8
Manual de Polymer
bower init
Seguidamente vamos a instalar la librería Polymer, que consigues con el siguiente comando de Bower:
Ahora fíjate que se ha creado la carpeta bower_components y dentro de ella tienes dos subcarpetas:
Para comenzar tienes la carpeta "bower_components" que es donde guardas tus dependencias. Por ahora solo tenemos
Polymer, pero más adelante tendrás aquí muchas otras carpetas de componentes que son muy útiles para cualquier
desarrollo.
Luego, y esto es algo importante de cara a la organización, tendrás una carpeta llamada "elements" que es donde
guardas todos los componentes que desarrolles tú mismo. En elements además tendrás una carpeta para cada uno de los
componentes. En resumen, cada componente en su carpeta y dentro de ella tendrás el código de tu componente y todo
aquello que ese componente pueda necesitar. Incluso el testing de un componente, documentación o el demo se colocará
en la carpeta del componente.
El resto será tal como a ti te interese. No obstante, si quieres ser mucho más ordenado, te recomendamos estudiar otras
estructuras de proyecto en las que en este momento no vamos a entrar. Un excelente ejemplo es el Polymer Starter Kit.
Nuestro componente se llamará "saludo-polymer", luego la ruta del fichero del componente será elemenst/saludo-
polymer/saludo-polymer.html.
Nota: Todos los componentes deben tener el carácter guión (el menos) en su nombre, al menos una vez, para
desarrolloweb.com/manuales/polymer.html Página 9
Manual de Polymer
Sin querer entrar en mucho detalle, puesto que más adelante en el Manual de Polymer explicaremos cada cosa con
mucha más profundidad, el código de nuestro componente es el siguiente:
Como ves, primero se realiza un import de la librería Polymer, que es una de nuestras dependencias en
"bower_components".
Luego ves que todo nuestro componente está dentro de una etiqueta dom-module, en la que declaramos el nombre del
componente que se está creando. Además cada componente tiene la parte visual, que es el template, con su HTML y CSS,
y la parte funcional y el registro del componente, en el SCRIPT. Observa que el registro de un componente tiene en estos
momentos únicamente expresado su nombre. Sigue leyendo este manual para mayores detalles.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>usando componentes</title>
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="elements/saludo-polymer/saludo-polymer.html">
</head>
<body>
<h1>probando</h1>
<saludo-polymer>Miguel</saludo-polymer>
</body></html>
Somos conscientes que hemos dejado pasar muchos detalles importantes para entender del todo este ejemplo básico,
pero no te preocupes porque tienes un excelente manual de Polymer por delante donde se irán aclarando todas las
dudas.
Además puedes ver el vídeo que encuentras a continuación donde se ve paso por paso todo lo explicado en este artículo
y varias otras cosas adicionales. Te recomendamos invertir 15 minutos de tu tiempo para verlo con calma.
desarrolloweb.com/manuales/polymer.html Página 10
Manual de Polymer
Vamos a conocer Polymer por la práctica desempeñando una de las posibilidades que nos ofrece la
librería, el uso de elementos, o componentes, que están disponibles en el catálogo de Polymer.
En este artículo vamos a realizar una primera práctica con Polymer al alcance de cualquier persona, incluso sin ningún
conocimiento de programación. Se trata de usar los componentes que nos ofrece en su catálogo de elementos.
Pero antes de comenzar aclaremos una cosa. Y es que, básicamente, cuando usas Polymer puedes hacer dos cosas
diferentes:
A) Por una parte existe la posibilidad de usar componentes que Polymer te ofrece, o aquellos creados por terceras
personas. Para esto no necesitas ningún conocimiento sobre programación y casi nada sobre el propio Polymer. El
catálogo de elementos de Polymer es muy grande y te aporta muchas utilidades para desarrollar cosas comunes, pero
además existe una comunidad muy activa creando y publicando constantemente como software libre nuevos elementos
que podrás también usar.
B) Como segunda alternativa, con Polymer podrás crear tus propios componentes para resolver necesidades específicas
para tus propios proyectos. Para esta segunda opción sí necesitas conocer la librería y, obviamente, ayudará tener
algunas nociones de programación.
Nota: A lo largo del manual de Polymer usaremos la palabra "componente" como sinónimo de "elemento". En
resumen nos referimos siempre a lo que en la especificación de Web Components sería un Custom Element, que
viene a ser una etiqueta personalizada que puedes crear para extender el HTML. Hay autores que incluso pueden
usar familiarmente la expresión "un Polymer" para referirse a un Custom Element desarrollado con la ayuda de la
librería Polymer.
Como debes saber, Bower funciona desde el terminal. Una vez tienes Bower en tu ordenador te dirigirás a la carpeta de
tu proyecto desde la línea de comandos. Instalas Polymer con el comando:
desarrolloweb.com/manuales/polymer.html Página 11
Manual de Polymer
Nota: Ya lo sabrás, pero si ya has creado tu bower.json te ayudará hacer un bower install --save polymer para que se
guarde la dependencia en el bower.json.
Polymer lo necesitas para poder usar cualquier elemento creado con esta librería. El polyfill lo necesitas para los
navegadores que todavía no soportan el estándar de los Web Components. En resumen el polyfill es una capa de
compatibilidad que permite que los navegadores que no tienen soporte nativo al estándar lo puedan entender por medio
de una librería Javascript. Hablaremos más tarde de él.
Nota: Un detalle interesante es que este paso, de instalar Polymer, realmente no necesitaríamos hacerlo
manualmente, pues al instalar mediante Bower cualquier elemento basado en Polymer se instalarán
automáticamente sus dependencias, en este caso la propia librería Polymer. De todos modos, está bien que lo
conozcas porque a veces quieres instalar Polymer independientemente de uno de sus elementos.
En la documentación del catálogo de elementos encontraremos sus explicaciones detalladas, junto con un demo y otros
recursos para aprender a usarlos. Allí también está detallado el comando de Bower que instala los componentes.
Vamos a elegir un componente cualquiera e instalarlo. Por ejemplo usaremos el que nos permite tener una barra de
desplazamiento para seleccionar un valor entre un mínimo y un máximo. Se conoce como "paper-slider" y su
documentación está en la siguiente URL: https://elements.polymer-project.org/elements/paper-slider
En la parte de la izquierda encontramos el comando para descargar el componente en nuestro proyecto, que tendrá esta
forma:
desarrolloweb.com/manuales/polymer.html Página 12
Manual de Polymer
Nota: Fíjate que el commando Bower tiene la opción --save, así que para que no te de error debes tener creado tu
bower.json en el proyecto. Lo creas cómodamente con bower init, como explicamos en el primero de los artículos que
hemos publicado dedicados a Bower. Si no tienes creado el bower.json y no lo quieres crear, simplemente quita la
opción --save.
Al ejecutar el comando anterior verás como en la carpeta bower_components se almacenan otra serie de carpetas, con el
código del elemento que queremos instalar, el paper-slider, y sus dependencias. Ahora que tenemos todos esos
componentes estamos en disposición de comenzar a usarlos.
Usar un componente
1. Esta es la parte más fácil y consta de dos pasos:
2. Importar el componente que deseamos usar, de modo que el navegador sepa dónde se encuentra su código fuente
3. Usarlo como si fuera cualquier etiqueta de HTML común
Importar el componente lo consigues con la etiqueta LINK del HTML. Esta etiqueta te permite acceder a un archivo .html
que tiene el código del custom element, tanto su HTML como el Javascript y el CSS, por medio de un único fichero. Estos
"import" forman parte de la especificación de los Web Components, aunque la etiqueta LINK en sí ya estaba con nosotros
hace años. Puedes encontrar más información en el artículo de los Imports de Web Components.
Nota: Fíjate que esta etiqueta LINK tiene el rel="import", mientras que para traerse una hoja de estilos externa, el
uso anterior que teníamos de esa etiqueta ese atributo tenía el valor "stylesheet". Fíjate también que la ruta al
código del elemento, atributo href, esté correcta.
Ese import lo colocarás en el HEAD de tu página. Posteriormente, en el cuerpo del documento HTML podrás usar
perfectamente la etiqueta nueva del elemento, como si fuera cualquier etiqueta común del HTML.
<paper-slider></paper-slider>
desarrolloweb.com/manuales/polymer.html Página 13
Manual de Polymer
Solo un detalle importante que debes tener en cuenta: para que estos ejemplos funcionen tienes que acceder a
las páginas a través de un servidor web. El motivo es que los import de Web Components traen los archivos que
estás importando por medio del protocolo HTTP. Si no los abres accediendo a un servidor web por HTTP no se podrá traer
el código del elemento paper-slider.
Nota: Usar un web server es una tarea muy sencilla. Si tienes un programa como wamp, xampp, mamp o similares,
ya cuentas con un servidor web. Si no, puedes usar el editor Brackets que el preview tiene incorporado uno (el icono
del rayo arriba a la derecha). Otra opción es usar algún servidor de un package NodeJS como http-server o polyserve.
Si no tienes nada de esto puedes subir los ejemplos, junto con la carpeta bower_components, a un servidor web
aunque no es lo más fácil y no lo recomendamos a nivel de desarrollo por ser una operativa muy poco práctica.
Estamos seguros que podrás superar este requisito. En el propio DesarrolloWeb.com tienes artículos para aprender a
usar varios servidores web.
La recomendación es colocar el script del Polyfill en el HEAD de la página. Obviamente, antes de hacer el import de
cualquier componente que quieras usar.
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
Solo tienes que fijarte que la ruta al script esté correcta. Todo depende de donde hayas colocado los elementos de Bower
y el HTML donde los estés usando.
El polyfill viene con varias alternativas. Las que tienen "min" quiere decir que el código está minimizado (ocupa menos
espacio en bytes y por tanto es más recomendable para un sitio en producción). Las que tienen "lite" es que incluyen
menos cosas, aunque en la mayoría de los casos son suficientes para hacer todo lo que necesites.
Ejemplo completo
El HTML del ejemplo sería el siguiente. Para asegurarte que funciona solo tendrás que haber instalado los archivos de
Polymer y del custom element como hemos descrito en los anteriores pasos.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Probando elemento de Polymer, paper-slider</title>
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="bower_components/paper-slider/paper-slider.html">
</head>
<body>
<h1>Probando paper-slider</h1>
<paper-slider></paper-slider>
</body></html>
Este documento HTML es el que tienes que abrir a través de un servidor web para que funcione el ejemplo. Como tiene
cargado el polyfill debería funcionar en todos los navegadores, salvo Explorer 9 y anteriores.
desarrolloweb.com/manuales/polymer.html Página 14
Manual de Polymer
Una de las posibilidades de Polymer es usar componentes que están en el catálogo de elementos, ya disponibles para
implementar en cualquier proyecto. Existen muchos componentes interesantes dentro de Polymer pero uno de los que
más llama la atención es el de los mapas de Google, dado que hacer un mapa no es una tarea trivial, pues necesita
bastante código Javascript para configurar sus diferentes opciones de presentación.
Cuando quieres implementar un "Google Map" dentro de una página web tienes varias opciones, algunas más fáciles y
otras más difíciles pero que también aportan ventajas.
Mapa sencillo con un iframe: el propio Google te permite configurar una especie de Widget que de una manera sencilla te
permite integrar un mapa por medio de un iframe. El problema es que las posibilidades de configuración son demasiado
básicas.
Mapa complejo e interactivo a través de un API. Si tienes necesidades mayores puedes de ecantarte por el API de los
mapas de Google y aprender a colocar marcas en mapas, trazados, etc. El problema es que el API es complejo de trabajar
y necesitas saber bastantes cosas de programación.
Nota: En DesarrolloWeb.com tenemos un manual para desarrollo completo de mapas de Google, aunque
actualmente la versión de la API ya ha cambiado, por lo que se encuentra desactualizado.
desarrolloweb.com/manuales/polymer.html Página 15
Manual de Polymer
Pero ahora, gracias a la librería Polymer, existe una alternativa intermedia, que es tan sencilla de usar como el widget,
que te lo da todo hecho, pero con unas posibilidades de configuración muy interesantes, sin tener que complicarte
aprendiendo su API. Obviamente si aprendes el API tendrás muchas más herramientas y alternativas, pero el 90% de las
cosas que querrás hacer con los mapas ya te las ofrece Polymer de una manera muy fácil.
Verás que crear tus mapas de Google y añadir elementos como marcas, así como aplicar alguna interacción sencilla
es tan fácil como saber usar una etiqueta HTML.
Nota: En este bloque del artículo te vamos a enseñar cómo se usan componentes ya creados en Polymer, aunque de
manera resumida. Si quieres más información y detalles sobre cómo instalar elementos de Polymer y asegurarte que
sean compatibles con todos los navegadores te recomendamos la lectura del artículo Usar elementos de Polymer.
Cuando aprendes esta tarea tendrás a tu disposición no solo un elemento de Polymer como los mapas de Google
sino toda una biblioteca de elementos listos para usar con los que enriquecer una web. Te recomendamos echar un
vistazo al catálogo de elementos de Polymer.
El elemento, o Custom Element, que vamos a instalar se llama "google-map". Como hemos dicho, sirve para eliminar la
complejidad de la integración de los mapas a una simple etiqueta HTML que expresa de manera declarativa las
propiedades del mapa a representar.
Sería bueno que analizáses esa página, pues así te irás familiarizando con la documentación de los elementos que nos
aporta Polymer. Encontramos diversas informaciones útiles, como el paquete donde se localiza este custom element, el
comando Bower para la instalación en un proyecto, un demo y una guía de uso del componente.
Nota: Para gestionar las dependencias de componentes en Polymer se recomienda el uso de Bower, del que puedes
encontrar un tutorial en el artículo Usar el gestor de dependencias Bower.
1.- Creamos carpeta de proyecto. Esto es un directorio vacío donde iremos colocando todos los archivos y carpetas de un
sitio o aplicación web. Si ya tienes esa carpeta de proyecto creada sería simplemente situarte con el terminal (línea de
comandos) dentro de esa carpeta.
2.- Desde una ventana de terminal, situados en la carpeta raíz de nuestro proyecto, tenemos que iniciar Bower con el
comando init de Bower:
bower init
Obviamente, si ya usas Bower e ese proyecto quizás tengas que saltar este paso.
3.- En la página de documentación del componente encontramos el comando de Bower para instalar la dependencia del
web component para los mapas de Google. Ese comando lo lanzamos por consola, desde la carpeta raíz del proyecto:
desarrolloweb.com/manuales/polymer.html Página 16
Manual de Polymer
Es interesante señalar que mediante ese comando se instala la etiqueta para generar mapas de Google, pero también
todas las dependencias que tiene. Todos los archivos se encuentran instalados en la carpeta "bower_components".
4.- Ya en la página donde queremos usar los mapas de Google, importamos el componente con la etiqueta LINK. Es un
simple "import" del estándar "Web Components" que hemos explicado anteriormente: Import en Web Components.
Solo tendrás que verificar que la carpeta bower_components esté en la ruta que has definido en el atributo href del
import.
5.- Ahora ya tenemos instalado el código de la etiqueta personalizada, paso realizado con Bower, y lo tenemos enlazado
con el documento HTML donde queremos usarla, gracias al import. De modo que está todo listo para usar el componente,
con la etiqueta google-map.
Como seguramente estás apreciando, esta etiqueta permite indicar como atributos diversas características del mapa a
mostrar. En nuestro caso hemos indicado los atributos más fundamentales, pero hay diversos otros que puedes conocer
en la documentación del componente.
Con esto conseguimos un mapa que estará centrado en la ciudad de Madrid (Esto se ha señalado mediante la latitud y
longitud indicadas en los correspondientes atributos) y con zoom suficiente para ver varias de sus "ciudades satélite".
6.- Solo un detalle y es que el mapa, por definición del API, necesita estar en un contenedor cuyas dimensiones de altura
hayan sido definidas. Por ello en este caso concreto vamos a colocar un estilo CSS adicional para el mapa.
<style>
google-map {
height: 400px;
}</style>
Nota: Este paso, de colocar un CSS al mapa es algo necesario con este componente, aunque sin embargo la mayoría
desarrolloweb.com/manuales/polymer.html Página 17
Manual de Polymer
de los elementos de Polymer ya tienen un CSS definido de manera predeterminada, para no tener que escribirlo a
mano cada vez q lo usamos. En el caso de la altura del mapa es porque los elementos de la página no crecen en la
altura, a no ser que se lo indiques de manera explícita con CSS. Como la etiqueta google-map no puede adivinar la
altura que tú quieres colocar, es necesario definirla a mano. La anchura la tomará del elemento donde hayas
colocado el mapa, o sea, su contenedor, aunque si quisieras también podrías asignar el atributo width al elemento
para que tenga la anchura deseada independientemente del contenedor.
Otra cosa que quizás resulta obvia pero que queremos remarcar es que hemos definido el estilo para la etiqueta google-
map directamente, por lo tanto afectará a todos los google-map que haya en la página. Podrías perfectamente colocar el
estilo a través de un identificador del mapa (atributo id) o una clase CSS (atributo class) del elemento en concreto que
desees afectar con los estilos.
Dada su latitud y longitud, escogidas mediante los correspondientes atributos, aparecerá encima del recinto "Casa de
Campo" de Madrid. El atributo "title" solo es un pequeño tooltip que aparece al poner el puntero del ratón encima de la
marca, igual que los "title" que conocemos en elementos como los enlaces. Pero quizás quieras aprender a hacer un
globo de información a visualizar cuando se haga clic encima de la marca.
Esto es tan sencillo como colocar el HTML que queremos en el globo informativo dentro de la etiqueta "google-map-
marker".
Puedes probar este ejercicio. Es muy fácil y verás como en el globo aparecen todos estos datos, tanto titular como
párrafo e imagen. Si no cabe todo se generará una barra de scroll.
desarrolloweb.com/manuales/polymer.html Página 18
Manual de Polymer
Conclusión
Esto es solo una muestra de lo que puedes conseguir fácilmente con elementos de Polymer y un par de características de
las muchas que podrás conseguir con las etiquetas para realizar mapas de Google. Estas etiquetas que hemos visto
contienen muchos otros atributos para personalizarlas, así como también existen otros elementos relacionados con los
Google Maps, como por ejemplo para colocar direcciones o trazados poligonales. Es solo cuestión de experimentar con
ellos y documentarse en la página del catálogo de elementos de Polymer.
Además estos elementos contienen diversos eventos personalizados con los que realizar acciones cuando el usuario
interactúe con el mapa y de ese modo poder agregar interactividad a los mapas. Veremos ejemplos sobre todo esto más
adelante.
Para finalizar a modo de referencia y por si hubiera alguna duda, dejamos el código completo del ejercicio que hemos
realizado en este artículo.
desarrolloweb.com/manuales/polymer.html Página 19
Manual de Polymer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>probando mapas</title>
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="bower_components/google-map/google-map.html">
<style>
google-map {
height: 400px;
}
</style>
</head>
<body>
<google-map latitude="40.4" longitude="-3.7" zoom="11">
<google-map-marker latitude="40.421432" longitude="-3.7536663" title="Casa de Campo de Madrid">
<h2>Casa de Campo de Madrid</h2>
<p>
Recinto amplio donde encontramos parques, lagos, zoológico, etc.
</p>
<p>
<img src="http://www.guiarte.com/archivoimg/general/1563.jpg" alt="Vista de Madrid desde la casa de campo">
</p>
</google-map-marker>
</google-map>
</body></html>
desarrolloweb.com/manuales/polymer.html Página 20
Manual de Polymer
Parte 2:
Creación básica de componentes con
Polymer
Nos adentraremos en el desarrollo de Web Components usando la librería Polymer.
Cómo registrar nuestros primeros elementos Polymer y acciones básicas que se puede
realizar con ellos.
La gracia de Polymer es que seamos capaces de crear nuestros propios componentes, es decir, lo que serían custom
elements para realizar cualquier tipo de tarea que requiera un proyecto.
Este artículo contiene un tutorial básico para crear un Custom Element con Polymer, lo que sería el "Hola Mundo" del
desarrollo de componentes Polymer. A lo largo de los próximos minutos podrás crear tu primera etiqueta HTML
personalizada capaz de tener un comportamiento elemental, básicamente mostrar un mensaje al usuario.
Por supuesto, los conocimientos que ya tenemos en cuanto a la creación de componentes con Javascript "nativo" (sin usar
librerías adicionales) nos servirán para poder entender mejor las piezas del desarrollo de componentes en Polymer.
Además, basando nuestro componente en esta librería, reduciremos bastante las necesidades de código fuente para
crear nuevos elementos con los que enriquecer la web.
En este caso vamos a crear dos archivos HTML: uno para la definición del custom element y otro para usar el elemento
recién creado, a modo de demo. Para nuestro ejemplo vamos a realizar una caja de feedback con la que podremos
presentar mensajes a nuestros usuarios.
desarrolloweb.com/manuales/polymer.html Página 21
Manual de Polymer
2.- Incluimos las dependencias. En este caso solo voy a depender de la librería general de Polymer, pero como veremos
más adelante, unos componentes se pueden crear en base a otros, en cuyo caso habría dependencias no solo con
Polymer, sino con otros elementos de la librería.
Generalmente esa línea del "import" la tendrás al principio de tu archivo del Custom Element.
3.- Definimos el elemento con . Esa etiqueta, propia de Polymer, mantiene en un mismo bloque todas las partes que
queramos agrupar en un custom element: HTML, CSS y Javascript. En esta etiqueta debemos colocar el nombre del
elemento que estamos generando en su atributo id.
<dom-module id="dw-feedback"></dom-module>
Entre esas etiquetas DOM_MODULE colocaremos a continuación todo el código del componente.
<dom-module id="dw-feedback">
<template>
<p>Hola Mundo</p>
</template></dom-module>
De momento hemos colocado simplemente la etiqueta TEMPLATE con un simple párrafo, será el único elemento en el
DOM local. Enseguida mejoraremos eso.
5.- Registramos el elemento con Javascript, para lo que usamos la función Polymer(), indicando un objeto con una serie de
parámetros. En este caso solo indicamos el nombre del elemento que queremos registrar "dw-feedback", pero más
adelante aprenderemos qué otros parámetros podemos usar a la hora de registrar el componente.
<dom-module id="dw-feedback">
<template>
</template>
<script>
Polymer({
is: 'dw-feedback'
});
</script></dom-module>
desarrolloweb.com/manuales/polymer.html Página 22
Manual de Polymer
Nota: Apreciarás que el nombre del custom element que estamos creando lo encontramos ya en dos localizaciones,
en el atributo id de DOM_MODULE y en la propiedad "is" del objeto enviado a la función Polimer().
Nuestro componente está terminado. Luego lo perfeccionaremos más, pero de momento ya tenemos algo para comenzar.
Ahora nos toca usarlo.
6.- Para usar el elemento recién definido creamos otro archivo aparte, donde importaremos el componente. Todos los
componentes de Polymer que creemos podremos usarlos las veces que queramos, en cualquier otra página. Para ello
simplemente tendremos que asociar el archivo del componente "dw-feedback", haciendo el correspondiente import del
archivo de definición del custom element.
Luego podremos usar el elemento en cualquier lugar del código HTML, con la etiqueta recién definida.
<dw-feedback></dw-feedback>
En este punto podríamos ejecutar la página donde estamos usando el elemento para ver cómo funciona. Deberíamos ver
el párrafo definido en la etiqueta TEMPLATE, que recuerda teníamos tal que así.
<template>
<p>Hola Mundo</p></template>
Vamos a incrementar alguna otra utilidad interesante al código de nuestro componente Polymer, ya que tal como lo
tenemos la verdad es que no es demasiado impresionante.
Veamos una muestra del código de un Custom Element como el nuestro en el que le hemos agregado los estilos:
<dom-module id="dw-feedback">
<template>
<style>
:host {
background-color: #de8a0b;
padding: 5px 10px;
color: aliceblue;
font-family: sans-serif;
display: block;
border-radius: 6px;
}
p{
font-weight: bold;
}
</style>
<p>
Hola Mundo
</p>
</template>
<script>
Polymer({
is: 'dw-feedback'
});
</script></dom-module>
Lo interesante de esos estilos es que no salen para afuera del componente. Se limitan solamente a estilizar el DOM local
desarrolloweb.com/manuales/polymer.html Página 23
Manual de Polymer
Todavía no hemos explicado qué significa el :host, pero te adelantamos que es el propio componente que se está usando
como host de todo el DOM local declarado en el TEMPLATE. Más adelante lo veremos con calma.
<dw-feedback>
Este es el mensaje personalizado </dw-feedback>
Ahora, en la definición del custom element, podemos volcar el contenido de la etiqueta con el tag CONTENT.
<p>
<content></content></p>
Cuando se renderice este elemento en la página, la etiqueta CONTENT se sustituirá con lo que se haya escrito dentro de
DW-FEEDBACK.
Al usar el custom element definimos el bloque de contenido de alguna manera. Por ejemplo indicando un nombre de class
CSS.
<dw-feedback>
<span class="message">Este es el mensaje personalizado</span></dw-feedback>
<p>
<content select=".message"></content></p>
En el siguiente código tenemos una versión de nuestro componente dw-feedback en la que usamos esta técnica de cargar
contenido definido mediante selector.
desarrolloweb.com/manuales/polymer.html Página 24
Manual de Polymer
});
</script></dom-module>
Al usar el componente tendremos que colocar los contenidos que se espera situar dentro de la capa del mensaje. Fíjate
que en el código de Polymer había dos etiquetas CONTENT, cada una de ellas trae un contenido distinto que se define
dentro de la etiqueta DW-FEEDBACK.
<dw-feedback>
<span class="message">Este es el mensaje personalizado</span>
<span class="messagetype">Alerta</span></dw-feedback>
Nota: Esta no es la única manera de colocar un contenido dentro de un elemento en Polymer. Veremos otras
también bastante prácticas más adelante.
De momento es todo. Tienes bastantes conocimientos y herramientas para probar unas cuantas cosas con Polymer.
Implementaremos nuevas mejoras en este componente más adelante para seguir aprendiendo cosas sobre esta
estupenda librería para desarrollo de Web Components.
Para la creación de un Custom Element el paso más importante y fundamental es realizar el registro de esta etiqueta.
Esto ya lo explicamos de manera práctica en el artículo sobre Crear elementos con Polymer, y ahora vamos a profundizar
un poco más conociendo algunos detalles del ciclo de vida de los componentes Polymer. Como verás, algunas cosas
están marcadas por el propio estándar de los Web Components y otras son cosas que tienen relación específica con la
librería Polymer.
desarrolloweb.com/manuales/polymer.html Página 25
Manual de Polymer
La declaración de funciones para ejecutar cosas en los diferentes estados de un componente se realiza mediante
métodos que tienes que definir en el objeto que envías a la función Polymer() para registrar un componente.
Polymer({
is: 'componente-ejemplo',
nombreMetodo: function() {
// código del método
}});
El detalle aquí es conocer las funciones que existen en Polymer para implementar acciones en el ciclo de vida:
Nota: Estos métodos son los mismos que en los web components, solo que en el estándar tienen la palabra
"Callback" atrás, como sufijo: createdCallback, attachedCallback, etc. Incluso dentro de un componente Polymer
podrías usar la función nativa de Javascript si lo deseas o como alternativa fallback.
ready: este método es propio de Polymer y no existe en el estándar. Se ejecuta cuando se ha terminado de crear e
inicializar todo el DOM local de un elemento, osea, todo el HTML que contiene en su TEMPLATE
desarrolloweb.com/manuales/polymer.html Página 26
Manual de Polymer
<script>
Polymer({
is: 'ciclo-vida',
created: function() {
console.log('método created');
},
ready: function() {
console.log('método ready');
},
attached: function() {
console.log('método attached');
},
detached: function() {
console.log('método detached');
},
attributeChanged: function() {
console.log('método attributeChanged');
}
});
</script></dom-module>
El elemento no tiene mucha utilidad, salvo la de poder acompañar los mensajes que hemos generado en cada una de las
etapas del "lifecycle".
Puede parecer mucho código, pero no te confunda, la parte importante es donde se coloca el custom element y luego
simplemente hay una serie de botones con acciones para forzar diversos estados del ciclo de vida que no se pueden
apreciar si no manipulamos la página. Después verás un SCRIPT para definir los comportamientos a esos botones que
explicamos a continuación.
desarrolloweb.com/manuales/polymer.html Página 27
Manual de Polymer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo dw-feedback</title>
<link rel="import" href="ciclo-vida.html">
</head>
<body>
<H1>Demo ciclo-vida</H1>
<ciclo-vida></ciclo-vida>
<button id="cambiaAtributo">Cambia Atributo</button>
<button id="quitaElemento">Quita el elemento del DOM</button>
<button id="creaElemento">Crea un nuevo elemento en memoria Javascript</button>
<button id="creaInyectaElemento">Crea un nuevo elemento e injecta en el DOM</button>
<script>
document.getElementById('cambiaAtributo').addEventListener('click', function(){
document.querySelector('ciclo-vida').setAttribute("atributo", 'valor');
});
document.getElementById('quitaElemento').addEventListener('click', function(){
document.body.removeChild(document.querySelector('ciclo-vida'));
});
document.getElementById('creaElemento').addEventListener('click', function(){
document.createElement('ciclo-vida');
});
document.getElementById('creaInyectaElemento').addEventListener('click', function(){
var elem = document.createElement('ciclo-vida');
document.body.appendChild(elem);
});
</script>
</body></html>
método created
método readymétodo attached
Porque primero se crea el elemento, luego se procesa su DOM local y una vez terminado de procesar se añade al
documento.
Luego, los otros botones hacen diversas acciones para cambiar un atributo, quitar un elemento de la página, crearlo y
añadirlo al documento.
document.querySelector('ciclo-vida').setAttribute("atributo", 'valor');
Esta sentencia hace que se cambie un atributo del elemento seleccionado con el selector "ciclo-vida". Entonces veremos
el mensaje
método attributeChanged
document.body.removeChild(document.querySelector('ciclo-vida'));
Ese código hace que se quite de la página un elemento con el selector 'ciclo-vida'. Entonces debemos ver el mensaje:
método detached
Cuando se crea desde cero un componente, sin llegar a insertarlo en el DOM de la página.
document.createElement('ciclo-vida');
Ese código crea un nuevo elemento con Javascript. El elemento no se crea más que en la memoria del navegador, pero no
desarrolloweb.com/manuales/polymer.html Página 28
Manual de Polymer
método created
método readymétodo attached
Conclusión
Con esto ya sabemos algo más de los componentes de Polymer y hemos podido encontrar alternativas de situar código
que nos pueden sacar de un apuro más de una vez. Deberías experimentarlas en tu propio ejemplo y familiarizarte con
ellas, puesto que son recursos útiles en varios casos.
Personalmente las que más uso son ready y attached, pero con moderación, porque lo cierto es que en Polymer hay
muchos mecanismos para hilar fino y hacer cosas cuando ocurren muchas otras situaciones relacionadas con los
componentes, como es el caso de los observers, que nos permiten vigilar por cualquier cambio de un atributo concreto,
por ejemplo. Así que dentro de poco aprenderás muchas otras alternativas que complementarán este conocimiento y te
permitirán realizar cosas más específicas.
Antes de acabar te dejamos un vídeo interesante para complementar la información que has leído en este artículo y
donde ponemos en marcha el componente de ejemplo. En el vídeo verás además cómo se ejecutan los eventos del ciclo
de vida, a medida que manipulamos el DOM mediante Javascript.
Polymer es una librería muy amplia. Está plagada de cosas que podemos aplicar para sacarle su potencial y una de las
primeras con las que tendremos que trabajar son las propiedades. En este artículo comenzaremos a explicarlas con
detalle.
Las propiedades de un componente Polymer son como sus datos, es decir, cualquier información que maneje el web
component para trabajar la almacenaremos en forma de propiedad. Si conoces la programación orientada a objetos
seguramente puedas hacerte una idea de lo que estamos hablando, porque el concepto es el mismo, pero si no es así
tampoco te preocupes.
La característica fundamental de las propiedades en Web Components en general es que éstas forman parte de las
propias etiquetas HTML. Allí las conocemos en forma de atributos, de modo que pueden viajar desde la declaración del
HTML hacia el componente, para modificar su comportamiento. Aunque no tomes eso como la única verdad, puesto que
muchas propiedades podrán usarse solamente en el interior del componente, como si fueran privadas.
desarrolloweb.com/manuales/polymer.html Página 29
Manual de Polymer
Dentro del componente las propiedades podrán accederse tanto desde el DOM local (la template que usas para declarar
el HTML del custom element) como desde el código Javascript. Todo esto lo veremos a continuación.
Declaración de propiedades
Las propiedades las podemos declarar al registrar el componente mediante el atributo "properties" del objeto que
pasamos a la función Polymer(), usada para registrar un custom element.
Polymer({
is: 'vista-fecha',
properties: {
mes: {
type: String,
value: 'enero'
},
dia: {
type: Number,
value: 1
},
ano: {
type: Number,
value: 2016
}
}});
Allí colocaremos en notación de objeto toda la serie de propiedades que vamos a usar en un componente. Como índice
colocamos el nombre de la propiedad y como valor sus características.
La declaración más sencilla de una propiedad se realiza únicamente indicando el tipo de datos que va a contener:
Polymer({
is: 'vista-fecha',
properties: {
nombrePropiedad: String
}});
En este caso "nombrePropiedad" está indicando que será una cadena de caracteres. Sin embargo esto limita bastante las
posibilidades de la declaración de propiedades de Polymer, ya que la librería nos permite indicar asuntos de lo más
diverso como:
Tipo
Valor por defecto
Si se puede modificar desde fuera
Si se debe notificar a otros componentes cuando esta propiedad cambia
Qué se debe hacer cuando la propiedad cambie de valor
Etc.
desarrolloweb.com/manuales/polymer.html Página 30
Manual de Polymer
Iremos viendo todos estos casos de configuración de propiedades en el futuro con detalle.
Es tan sencillo como usar los propios atributos del HTML, indicando el valor de la propiedad entre comillas:
En este caso la propiedad "saludo" definida para el Component "nombre-componente" valdrá "Buenas tardes".
Con esta mecánica de definición de propiedades, mediante atributos en el HTML, podemos usar bindings, para enviar
valores de propiedad que provengan de variables u objetos que tengamos dentro de nuestra aplicación, incluso de
propiedades de otros componentes. El tema del binding es muy poderoso y básico para la creación de aplicaciones en
Polymer. No lo hemos visto todavía pero ahondaremos en ello en breve, pero si quieres ir adelantando algo puedes ver
cómo funciona con este vídeo que hemos publicado en Youtube: Binging entre componentes Polymer.
En el caso de un custom element realizado con Polymer la operativa se simplifica mucho, ya que las propiedades del
elemento son propiedades del propio objeto del DOM. Se ve más fácil con código que explicándolo.
document.querySelector("vista-fecha").mes = "abril"
Como puedes apreciar, accedemos a un custom element mediante el DOM, usando cualquiera de los métodos existentes
para ello con Javascript. En ese código usamos document.querySelector() pero podría haberse usado perfectamente
document.getElementById(), por ejemplo.
Sobre nuestro elemento "vista-fecha" accedemos luego a la propiedad "mes", que será una de las propiedades del
componente Polymer. Asignando cualquier valor se altera el valor de esa propiedad dentro del componente.
Para ello usamos una notación que seguramente conozcamos de populares sistemas de templating, las dobles llaves.
Dentro de dos llaves, de inicio y cierre, colocamos el nombre de la propiedad que se desee volcar como contenido de un
componente.
<template>
<div>
<span class="mes">{{mes}}</span>
<span class="dia">{{dia}}</span>
<span class="ano">{{ano}}</span>
</div></template>
desarrolloweb.com/manuales/polymer.html Página 31
Manual de Polymer
Nota: Ya que hemos usado el término "binding" antes en este artículo, podemos decir que en realidad este volcado
del valor de una propiedad es un caso de binding. La propiedad está enlazada con el template, de modo que si
cambia su valor también cambiará el contenido de ese elemento, de manera dinámica.
Se trata de un componente que contiene una vista de una fecha, en un pequeño recuadro de calendario con el valor de
un día concreto. No tiene ningún comportamiento dinámico y su único cometido es mostrarnos la fecha con un formato
determinado.
desarrolloweb.com/manuales/polymer.html Página 32
Manual de Polymer
},
ano: {
type: Number,
value: 2016
}
}
});
})();
</script></dom-module>
Todas sus propiedades son de tipo cadena y number. Hablaremos de los tipos más adelante. Además les hemos asignado
valores por defecto para que, si no se indican, se tomen aquellos que se han declarado en el objeto "properties".
Ahora puedes ver el código del demo que usaría este componente.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Probando vista-fecha</title>
<link rel="import" href="vista-fecha.html">
</head>
<body>
<h1>Probando vista fecha</h1>
<vista-fecha></vista-fecha>
<br>
<vista-fecha mes="febrero" dia="2" ano="2016"></vista-fecha>
<script>
document.querySelector("vista-fecha").mes = "abril"
</script>
</body></html>
Tenemos dos recuadros de fecha, uno con un elemento en el que no se indica ningún valor en los atributos "mes", "dia",
"ano" y otro en el que se han asignado esos valores de manera declarativa en el HTML.
Además hay un pequeño script para ver cómo de manera imperativa se puede cambiar una propiedad de un elemento,
mediante el propio DOM de la página.
Esperamos que esta primera introducción a las propiedades de componentes Polymer te haya servido para aclarar
bastantes conceptos básicos. Seguiremos tratando este tema en las próximas entregas. Para complementar esta
información puedes asistir a este vídeo, en el que mostramos el proceso de creación de este componente web:
Las propiedades de los elementos Polymer son una de las principales herramientas de cara al desarrollo de Web
Components. El artículo anterior del Manual de Polymer, ya proporcionamos bastante información las propiedades en
Polymer. Ahora vamos a ser un poco más formales y documentar con mayor detalle algunos de los datos que ya
introdujimos anteriormente.
Nos centraremos en el registro o declaración de propiedades, que contiene una larga lista de posibilidades de
desarrolloweb.com/manuales/polymer.html Página 33
Manual de Polymer
configuración que debemos conocer y aprovechar en el día a día del desarrollo con esta librería Javascript.
En el pasado artículo vimos que en el objeto "properties", que enviamos en el registro de un componente Polymer,
debíamos declarar una a una cada propiedad que queremos usar.
En esa declaración de la propiedad, indicada con bajo el objeto "properties", podemos hacer cosas como definir su tipo,
su inicialización, etc.
Nota: Ten en cuenta que esta primera descripción de los valores asignables a una propiedad la hacemos con
intención de dar una vista de pájaro a la declaración de propiedades. Hay muchas de estas configuraciones que
resultan un tanto complejas y que veremos con detenimiento en futuros artículos más específicos.
- type: Indicamos el tipo de dato que va a contener esta propiedad. En Polymer podemos usar los siguientes tipos de
datos, nativos de Javascript: Boolean, Number, String, Array, Object y además Date.
- value: es el valor de inicialización que asignamos a una propiedad, que será configurado de manera predeterminada.
Ese valor ya vimos en el pasado artículo que se puede cambiar de manera imperativa, simplemente asignando otro
mediante Javascript, o de manera declarativa, al indicarlo en el HTML.
properties: {
propiedad1: {
type: Boolean,
value: true
}}
También value puede estar asociado a un función que devuelva aquel valor con el que debemos inicializar la propiedad
de manera predeterminada. En este caso, la función se ejecutará cuando se genere una instancia del componente, para
asignar el valor que corresponda. Este sería el código para asignar un valor por medio de una función:
properties: {
personas: {
type: Array,
value: function(){ return ["mario", "gerardo"]; }
}}
Este tipo de construcción es muy habitual en el caso de propiedades de tipo array y objeto, dado que la función permite
que el array u objeto sea propio e independiente para cada instancia del componente.
- reflectToAttribute: Esta propiedad permite que, cuando desde dentro del componente o desde un Javascript externo,
desarrolloweb.com/manuales/polymer.html Página 34
Manual de Polymer
se cambie el valor de una propiedad, también se refleje en el código HTML del componente, cambiando su valor. Puede
recibir true o false y la reflexión hacia el atributo se dará en caso positivo. Dicho de otra manera, la propiedad en el HTML
del componente se sincronizará con el valor que tenga la propiedad en cada instante dentro del componente.
- readOnly: Es otro boleano, que indica si esta propiedad se puede alterar o no desde medios externos, como podría ser
una asignación o un bindeo.
- notify: Esta declaración es muy importante para el binding, del que solo hemos introducido el concepto todavía. En
concreto con notify (al que asignamos también un valor boleano) puedes definir si quieres que se notifique hacia afuera
los cambios en una propiedad. De manera predeterminada los componentes Polymer no notifican a sus padres (aquellos
componentes donde están incluidos) los cambios en sus propiedades. Asignando true a notify conseguimos que una
propiedad notifique hacia arriba (al padre) los cambios en una de sus propiedades, algo como decimos necesario para
producirse el "two-way-binding" que nos proporciona Polymer.
- computed: Esta es otra de las declaraciones de uso común. Nos sirve para indicarle que el dato o valor que guarda una
propiedad está computado, es decir, que para conocer su valor se necesita realizar una operación. Le indicamos como
valor el nombre del método que realizará el cómputo. En este mismo artículo explicamos con más detalle esta
declaración un poco más adelante.
- observer: Es otro string al que le asignamos el nombre de una función. Esta función, o mejor dicho método del
componente, se ejecutará cada vez que cambie el valor de esta propiedad. Dicho de otro modo, observer sirve para
indicar el método que debe ejecutarse cada vez que el valor de la propiedad cambie.
Todas las alternativas para declarar propiedades son útiles en innúmeros casos, sin embargo hay unas que se usan más
habitualmente que otras. Ahora vamos a ver un ejercicio sencillo de componente que nos ilustre el funcionamiento de
algunas de las cosas que hemos aprendido, pero antes vamos a hablar con detalle de una de las declaraciones anteriores.
Declaración computed
En ocasiones las propiedades en un componente pueden ser computadas. Esto quiere decir que nosotros calcularemos su
valor en función de otras propiedades.
Hay muchos casos de propiedades computadas en la vida real. Por ejemplo, el nombre completo de una persona, es una
unión del nombre de pila y los apellidos. La letra del NIF de personas físicas en España se puede calcular en función de su
número de DNI (Documento Nacional de Identidad). El área de una circunferencia se puede calcular en función de su
radio. Etc.
Pues bien, en Polymer las propiedades "computed" son aquellas que se pueden calcular en función de otros datos y su
valor cambiará cada vez que cambian estos datos. Por ejemplo en el caso de una circunferencia, se calculará el área en
función de su radio y si cambia el radio el valor del área tendrá que cambiar instantáneamente.
A la hora de definir una propiedad computada debemos indicar la declaración "computed", indicando como valor una
cadena con el nombre del método que realizará la computación junto con sus parámetros, que podrán ser los nombres de
otras propiedades. Para que el valor computado se altere en cada instante, esa función se ejecutará cada vez que los
valores de las funciones indicadas en los parámetros cambien.
properties {
radio: {
type: Number,
value: 1
},
area: {
type: Number,
computed: 'calcularArea(radio)'
}}
En este caso vemos que "area" es la propiedad computada. El método "calcularArea" que debemos crear en el
desarrolloweb.com/manuales/polymer.html Página 35
Manual de Polymer
componente recibirá el "radio", que es otra propiedad del Polymer que se necesita para calcular el área. Cada vez que la
propiedad "radio" cambie se invocará de nuevo a la función calcularArea() con el nuevo valor.
En este caso la gracia está en la propiedad computada "recorte", que almacena el valor que debemos mostrar, producido
al recortar el texto largo con una longitud dada. Por tanto nos salen tres propiedades:
Nuestro template simplemente muestra la propiedad {{recorte}}, bindeando gracias a las dos llaves de apertura y cierre.
Repara en el detalle que la propieddad que estamos bindeando al template, y que por tanto se verá en el espacio donde
se encuentre este componente Polymer, es aquella que hemos declarado como computed. Por tanto, lo que se mostrará
aquí será el valor una vez computado, con la función indicada para ello.
Fíjate en las propiedades señaladas, observando que en el caso de la propiedad "len" hemos asignado un valor
predeterminado para el recorte. En el caso de "str" (que es la cadena original antes del recorte), su valor predeterminado
es la cadena vacía.
Luego en la propiedad computada "recorte" tenemos la declaración computed, indicando el nombre de la función que
desarrolloweb.com/manuales/polymer.html Página 36
Manual de Polymer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Probando vista-fecha</title>
<link rel="import" href="rompe-cadena.html">
</head>
<body>
<h1>Probando rompe-cadena</h1>
<p>
<rompe-cadena str="Lo que el viento se llevó"></rompe-cadena>
</p>
<p>
<rompe-cadena str="Las dos caras de la moneda" len="10"></rompe-cadena>
</p>
</body></html>
desarrolloweb.com/manuales/polymer.html Página 37
Manual de Polymer
Parte 3:
Observers en Polymer
Los observers nos permiten vigilar u observar cambios en propiedades de componentes
Polymer. Son extremadamente útiles, además de sofisticados, porque con ellos puedes
centralizar en un lugar todo el código que debe desencadenarse al cambiar el estado
del componente. Puedes observar propiedades, conjuntos de propiedades, arrays,
atributos de objetos, etc. La optimización de los observers de Polymer hace que el uso
de esta herramienta sea un poco complejo cuando quieres observar atributos
profundos de objetos, así que hay que prestar especial atención.
Polymer contiene un juego muy potente de herramientas para trabajo con propiedades declaradas. De entre todas ellas,
hoy vamos a hablar de los “Observers”. Las propiedades de Polymer ya las tratamos en un artículo anterior, por lo que no
vamos a entrar en esos detalles. Nos centraremos entonces en cómo observar sus cambios por medio de los
mencionados observers.
Solo por aclarar, para quien venga de AngularJS, los observers vienen a ser como los “watcher”, pero algo más sencillos
de manejar. Seguramente otras librerías o frameworks ofrecen herramientas semejantes, dado que son muy útiles en
proyectos de desarrollo. Básicamente porque nos permiten centralizar en un único sitio todas las cosas que deben ocurrir
cuando hay un cambio en un dato. Cambie por el motivo que cambie ese dato (en Polymer será una propiedad), se
invocará al correspondiente observer cuando esto ocurra, si es que se ha definido alguno.
Existen dos maneras de trabajar con los observers. Una muy sencilla en la declaración de la propiedad y otra un poco
más compleja por medio de un array “observers” donde podemos declarar todos los observadores que queramos. La
manera sencilla la podemos usar siempre que lo que queramos observar una única propiedad. La manera compleja la
usaremos cuando queramos observar dos o más propiedades a la vez. Todo esto se verá con detalle a continuación, pero
antes de comenzar a entrar en harina, es importante ir avisando ya que observar casillas de un array o propiedades de
objetos tiene ciertas dificultades adicionales, luego lo comentaremos bien y explicaremos los motivos.
desarrolloweb.com/manuales/polymer.html Página 38
Manual de Polymer
Las funciones que asignas como observadores las podrías entender como una especie de manejador de evento asociado
al valor de la propiedad. Es solo un símil a nivel didáctico, porque un observer no es un evento, pero podrías decir que es
algo parecido a un evento que se dispara cuando cambia un valor, llamando a la función observadora que se haya
declarado.
Su uso es muy elemental, como verás a continuación. Vamos a ver primeramente la declaración de una propiedad donde
hemos definido un observer.
cuenta: {
type: Number,
value: 10,
observer: "vigilarFinCuenta"}
Ahora veamos el código de nuestra función observadora, que no es más que un método del propio componente, que
recibe como ves dos parámetros.
Cuando cambia la propiedad se envía a la función como parámetro el nuevo valor, así como el valor que anteriormente
hubiera en esa propiedad, por si nos hiciera falta para algo.
Nota: Es interesante mencionar que, en el código de la función anterior, this.cuenta sería equivalente al parámetro
valorActual. Podremos acceder a uno u otro indistintamente para acceder al valor actual de la propiedad.
El detalle en este tipo de observers es que solo podemos observar una propiedad individual. Si queremos observar
cuando una combinación de dos propiedades cambia, entonces tenemos que cambiar la estrategia y declarar
observadores de otro modo.
desarrolloweb.com/manuales/polymer.html Página 39
Manual de Polymer
Se debe indicar en el array, también como cadena, cada uno de los nombres de las funciones observadoras, con el juego
de parámetros equivalente a los nombres de propiedades que se están observando.
Las funciones observadoras son capaces de recibir los nuevos valores de las propiedades, una vez producido el cambio
observado. Pero a diferencia Igual del método anterior de definición de observers (aquellas funciones observadoras que
hemos calificado de simples, declaradas en en el objeto “properties”), en este caso no se nos informa del valor anterior
de la propiedad.
Este tipo de observer, declarado en el array "observers", tiene otra característica que lo diferencia y es que la funcion
observadora no se ejecutará hasta que el valor de ambas propiedades sea distinto de null o undefined. Dicho de otro
modo, el observer no empieza a estar operativo hasta que ambas propiedades tengan un valor definido.
Luego nos quedaría definir estas funciones observadoras, como métodos en el componente. Es similar a lo que ya hemos
conocido,
cambiaTask: function(task) {
console.log("cambiaTask", task, k);
},
cambiaTaskBoom(task, boom) {
console.log("cambiaTaskBoom", task, boom);}
Como te habrás dado cuenta, en el método de definición de observers no tenemos acceso al valor anterior de la
propiedad. Solo nos facilitan como parámetro el valor actual.
Esto es básicamente por motivos de rendimiento. Piensa en objetos complejos, con decenas de propiedades, que a su vez
pueden ser otros objetos con más propiedades todavía. Si el observar un objeto incluyera observar cada una de sus
propiedades, a cualquier nivel de profundidad, requeriría mucha cantidad de procesamiento, afectando al rendimiento. Lo
mismo con un array con cientos o miles de casillas, sería poco práctico estar observando los cambios en cada una de
ellas. Pero no es necesario preocuparse, porque existe un mecanismo para observar todo esto con el detalle que sea
necesario.
Publicaremos en breve un artículo para ver en detalle todos los casos posibles sobre la observación de propiedades de
objetos.
Este componente lo hemos creado simplemente con fines didácticos. Hace una sencilla cuenta hacia atrás y llegado el
valor cero, se muestra un mensaje. Tiene un par de detalles interesantes de ver.
desarrolloweb.com/manuales/polymer.html Página 40
Manual de Polymer
<p>
<paper-button on-tap="disparar" hidden="{{boom}}">Dispara</paper-button>
</p>
</template>
<script>
Polymer({
is: 'cuenta-atras',
properties: {
cuenta: {
type: Number,
value: 10,
observer: "vigilarFinCuenta"
},
task: Number,
boom: {
type: Boolean,
value: false
}
},
observers: ['cambiaTask(task)', 'cambiaTaskBoom(task, boom)'],
cambiaTask: function(task) {
console.log("cambiaTask", task);
},
cambiaTaskBoom(task, boom) {
console.log("cambiaTaskBoom", task, boom);
},
vigilarFinCuenta: function(valorActual, valorAnterior) {
console.log(valorActual, valorAnterior);
if(this.cuenta == 0){
this.cancelAsync(this.task);
this.boom = true;
}
},
decrementar: function() {
this.task = this.async(this.decrementar, 1000);
this.cuenta --;
},
ready: function() {
this.task = this.async(this.decrementar, 1000);
},
disparar: function() {
this.cuenta = 0;
}
});
</script></dom-module>
Luego hay un par de métodos helper: this.async() y this.cancelAsync(). Son equivalentes a los conocidos setTimeout() y
clearTimeout() de Javascript nativo. Los usamos en este ejemplo para conseguir que cada segundo se decremente la
cuenta hacia atrás en 1 unidad.
De momento eso es todo sobre Observer, aunque todavía hay cosas que se nos han quedado en el tintero y que debemos
completar en futuros artículos.
desarrolloweb.com/manuales/polymer.html Página 41
Manual de Polymer
Polymer
Cómo observar el cambio en propiedades de objetos, así como en casillas de un array en propiedades
de componentes Polymer.
Si queremos observar una propiedad de un objeto, no basta con observar el objeto completo, porque Polymer no nos
informará que ha cambiado, si lo que solo ha cambiado es su propiedad. En lo que respecta a los arrays es un poco
diferente, podemos observarlos pero solo nos informarán si se cambian por mecanismos propios de Polymer que
enseguida explicaremos.
Crearemos funciones observadoras, indicando como parámetro qué propiedad o conjunto de propiedades queremos
observar. Fíjate en el siguiente código.
Nota: Como alternativa podríamos haber definido una única función observadora, que vigilase cambios en ambas
propiedades del objeto "contadores".
Igual que antes, las funciones observadoras recibirán el nuevo valor asignado:
cambioAgotadas: function(valor){
console.log("cambio Agotadas, ahora vale: ", valor);}
desarrolloweb.com/manuales/polymer.html Página 42
Manual de Polymer
Nota: Mucha atención en este punto, porque no usar el correspondiente método set() cuando queremos cambiar
propiedades que deseamos observar es una fuente de errores muy habitual en Polymer.
this.set("contadores.agotadas", 5);
El método this.set() es de Polymer. Realmente forma parte del prototipo básico del que heredan todos los componentes
de Polymer, por lo que estará disponible siempre que lo necesites en el componente. Recibe una cadena con la propiedad
a modificar y el nuevo valor que se pretende asignar.
Insistimos, esta es una condición indispensable para que tus observer se disparen. Además, si tienes bindeadas las
propiedades a un template y quieres que ese valor nuevo de la propiedad también se transmita a todos los lugares donde
esté bindeado, deberás usar this.set().
Otro caso especial es que quieras observar todas las propiedades de un objeto y no quieras especificarlas una a una.
Entonces puedes usar el comodín asterisco *.
observers: ['mensajeDestinatarioCambiado(mensaje.destinatario.*)']
A la hora de definir la función observadora la propiedad que haya cambiado se recibe de una manera especial, ya que lo
que recibimos en este caso es un objeto con dos propiedades, la cadena con la ruta a la propiedad que cambió y luego el
valor nuevo que se asignó.
'mensajeDestinatarioCambiado: function(cambios) {
console.log('Atributo cambiado: ' + cambios.path);
console.log('Nuevo valor: ' + cambios.value);}
De momento solo vamos a enumerar las funciones de mutación de arrays: push, pop, shift, unshift, y splice. Todas
dependen del prototipo básico de todo componente Polymer, así que las invocaremos a partir de "this".
observers: ['cambiosArrayProductos(productos.splices)'],
Como ves, el array que estaríamos observando es "productos". Le agregamos ".splices" para decirle a Polymer que lo que
queremos es observar cambios en sus casillas.
Ahora en la función observadora podremos consultar qué elementos se han modificado, borrado o añadido, por medio del
parámetro que se le envía. Ese atributo es un registro de los cambios en el array.
cambiosArrayProductos: function(registroCambios) {
//en registroCambios tengo las modificaciones del array observadas}
Ese objeto que realiza el registro de los cambios es un poco complejo de usar, con respecto a lo que estamos
acostumbrados en otros observers. Preferimos detallarlo en ejemplos de futuros artículos. Mientras tanto puedes
consultar también la documentación de Polymer.
Se basa en el componente que hicimos en el artículo anterior de una cuenta atrás. Ahora tendremos varios contadores
desarrolloweb.com/manuales/polymer.html Página 43
Manual de Polymer
hacia atrás y queremos saber cuántos han llegado al final y cuántos no. En realidad este componente lo hacemos solo por
jugar un poco, tampoco tiene mucha más utilidad que la de enseñar código.
Esas propiedades se modifican desde dos métodos. Es importante ver como se usa el método set(), que es esencial para
que ocurran las notificaciones a los observer.
agotada: function() {
//this.contadores.agotadas ++ //eso no notificaría a nadie
this.set("contadores.agotadas", this.contadores.agotadas + 1);
},
disparada: function() {
this.set("contadores.disparadas", this.contadores.disparadas + 1);},
Y los métodos observadores que se encargan de realizar acciones cuando cambien los valores de las propiedades:
cambioAgotadas: function(valor){
console.log("cambio Agotadas, ahora vale: ", valor);
},
cambioDisparadas: function(){
console.log("cambio Disparadas");
},
cambioCualquiera(cambios){
console.log("En cambio cualquiera", cambios.path, cambios.value);}
Para ordenar las ideas, te dejamos el código completo de este ejemplo de componente:
desarrolloweb.com/manuales/polymer.html Página 44
Manual de Polymer
</template>
<script>
Polymer({
is: 'agotadas-disparadas',
properties: {
elementos: {
type: Array,
value: function() {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
}
},
contadores: {
type: Object,
value: function() {
return {
agotadas: 0,
disparadas: 0
}
}
}
},
observers: ['cambioAgotadas(contadores.agotadas)', 'cambioDisparadas(contadores.disparadas)', 'cambioCualquiera(contado
agotada: function() {
//this.contadores.agotadas ++ //eso no notificaría a nadie
this.set("contadores.agotadas", this.contadores.agotadas + 1);
},
disparada: function() {
this.set("contadores.disparadas", this.contadores.disparadas + 1);
},
cambioAgotadas: function(valor){
console.log("cambio Agotadas, ahora vale: ", valor);
},
cambioDisparadas: function(){
console.log("cambio Disparadas");
},
cambioCualquiera(cambios){
console.log("En cambio cualquiera", cambios.path, cambios.value);
}
});
</script></dom-module>
desarrolloweb.com/manuales/polymer.html Página 45
Manual de Polymer
Parte 4:
Binding en Polymer
En los siguientes artículos abordaremos con detalle los procesos de binding. Se trata de
una de las principales herramientas que tenemos en la librería Polymer para el
desarrollo acelerado y para facilitar, de una manera sencilla, la colaboración de unos
componentes con otros.
Una de las cosas más potentes que nos ofrece la librería Polymer es la operación que se conoce como binding. Si ya
sabes lo que es el binding de otras librerías o frameworks no habrá mucho que explicar conceptualmente hablando. Pero
si no es el caso te diremos que binding es una operación de enlace, por medio de la cual un dato puede estar relacionado,
mostrando su mismo valor en dos zonas distintas de la aplicación. La gracia es que, mediante el proceso de binding, si
ese dato cambia en un lado de la aplicación, el cambio se desencadena de modo que se actualicen todos los lugares
donde se está visualizando.
Al que viene de AngularJS seguro que una de las cosas que le impactaron es el binding en dos direcciones. También
existe en Polymer y funciona de manera muy similar. Si es tu caso seguramente te sentirás como en casa al acercarte a
Polymer.
El binding es muy amplio en Polymer, produciéndose a muchos niveles. Tenemos binding de un dato dentro del mismo
componente, binding entre componentes, binding en una dirección y en dos direcciones, etc. Iremos viéndolo en este
artículo y en los sucesivos. Realmente a lo largo de todo el manual hacemos uso del binding constantemente. Incluso
aunque solo ahora abordamos este asunto de manera particular, ya hemos realizado operaciones de "bindeo" en varias
ocasiones.
desarrolloweb.com/manuales/polymer.html Página 46
Manual de Polymer
Polymer({
is: "ejemplo-binding",
properties: {
titular: {
type: String,
value: 'Esto es un titular'
}
}});
Si queremos mostrar ese dato en nuestro componente lo bindeamos en el template mediante la expresión de las dos
llaves de inicio y de cierre.
<template>
<h1>{{titular}}</h1></template>
Cuando cambie la propiedad "titular" (algo que puede pasar por diversos motivos, como por ejemplo un script, respuesta
a un evento o porque desde fuera nos actualicen esa propiedad) automáticamente cambiará el titular H1 del
componente.
Ahora, en nuestro componente podemos tener ese binging hacia la propiedad "titular" en otros sitios.
<template>
<h1>{{titular}}</h1>
<paper-input label="Cambia el titular" value="{{titular}}"></paper-input></template>
Nota: Por si no lo sabes, un componente "paper-input" es como un elemento "input" de toda la vida, solo que
decorado con el diseño definido en "Material Design". Este, como muchos otros componentes, se encuentra
disponible en el catálogo de elementos de Polymer.
Ahora, si cambia la propiedad, cambiará automáticamente en ambos lugares del template, en lo que hay escrito en el
encabezamiento H1 y en lo que hay escrito dentro del "paper-input".
desarrolloweb.com/manuales/polymer.html Página 47
Manual de Polymer
En nuestro componente hasta el momento hemos colocado dos bindings y ya tenemos un binding de una y de dos
direcciones (one way & two way). Por si no ha quedado claro y antes de explicarlo con detalle, veamos el código completo
de nuestro componente.
Bindeo de 1 dirección:
Es cuando los datos viajan solo en un sentido. Es decir, enviamos los datos hacia un elemento, pero si cambian dentro de
ese elemento no se propagan.
Lo tienes en el caso del titular H1. En realidad en este caso es algo marcado por la propia naturaleza de la etiqueta H1,
puesto que lo que hay escrito dentro del encabezamiento no es un contenido editable de ninguna manera. En ese
encabezamiento los cambios van solo desde fuera hacia dentro. No hay como alterar el dato dentro del encabezamiento,
luego no hay binding desde él hacia fuera.
Por motivos de rendimiento en Polymer es posible indicar de manera explícita un binding en una sola dirección, incluso en
el elementos de naturaleza editable. Esto se hace con los corchetes en lugar de las llaves, como enseguida veremos.
Lo tienes en el caso del paper-input. Debido a que es un campo editable, si se cambia su contenido se alterará el valor de
la propiedad "titular" y por ello los cambios saldrán hacia afuera, propagándose hacia todos los lugares donde se
encuentre bindeado este dato.
Lo observaríamos si cambiamos las dos llaves por dos corchetes en el binding del paper-input:
En este caso, si se cambia el contenido del campo de texto, su nuevo valor no viajará hacia afuera y los otros elementos
que estén mostrando ese dato no se actualizarán.
Nota: Aunque parezca una desventaja el binding de una única dirección es muy interesante disponer de él, porque
no siempre se necesita un enlace a dos bandas. En el caso que no sea necesario podemos simplemente ahorrar esos
recursos a Polymer, optimizando el uso de la aplicación. Sin embargo, donde no hay posibilidad de binding en dos
direcciones, como era el caso del encabezamiento H1, Polymer no necesita que le indiques el binding de una
dirección de manera explícita, porque siempre será de una única dirección por la naturaleza del elemento.
Para nuestro componente de ejemplo, podemos cargarle el valor inicial de la propiedad "titular" por medio de un atributo
desarrolloweb.com/manuales/polymer.html Página 48
Manual de Polymer
En este caso hemos cargado un valor literal, pero ese valor también podría venir de un binding. Por ejemplo este
componente podríamos usarlo dentro de otro componente (o dentro de un template "dom-bind" que veremos más
adelante) y desde fuera poblar la propiedad "titular" por medio de otra propiedad que tengamos allí.
Nota: También puede haber tránsito de la información desde dentro del componente hacia afuera. Eso lo veremos
en el siguiente artículo.
Propiedades readOnly
Podemos modificar el comportamiento anterior, indicando que alguna propiedad es "readOnly", de solo lectura. Es algo
tan sencillo como indicarlo al declarar la propiedad.
properties: {
titular: {
type: String,
value: 'Esto es un titular',
readOnly: true
}}
Con esto conseguimos que, aunque nos asignen desde fuera valores o nos bindeen propiedades, en el interior de un
componente no se acepten dichos valores definidos de manera externa.
El tema del binding es bastante amplio y todavía hay bastante por ver, aunque seguro que con lo visto hasta ahora ya te
has hecho una buena idea de sus importantes posibilidades. En el siguiente artículo veremos, entre otras cosas, otra de
las propiedades relacionadas con el binding, que es "notify", para permitir que los cambios de un bindeo viajen hacia
fuera de un componente.
El binding es un enlace a un dato, de modo que todos los elementos que estén "bindeados" a ese dato puedan recibir
cualquier cambio de manera automácia. Esto ya lo conocimos en el artículo de introducción al binding en Polymer.
Ya vimos que dentro de un componente puedo bindear datos, generalmente propiedades, hacia el template. De modo
que si cambia esa propiedad también cambie la vista sin que tengamos que hacer nada. Ahora vamos a ver cómo entre
componentes también puede producirse el binding, permitiendo que un dato que se usa en un componente también
pueda viajar hacia otros componentes que lo necesiten.
desarrolloweb.com/manuales/polymer.html Página 49
Manual de Polymer
Al usar ese elemento le pasamos datos literales para adaptar su modo de funcionamiento. Cada vez que lo usamos le
enviamos datos distintos para mostrar diferentes cadenas con sus recortes. Hasta ahora simplemente le hemos enviado
datos literales, pero también podemos enviarle datos variables.
Por ejemplo imagínate que estás dentro de un componente y tienes la cadena a romper en una propiedad llamada
"cadena". Podríamos usar el elemento anterior indicándole que su propiedad "str" esté bindeada con la variable "cadena".
Lo hemos explicado muy rápido, pero ahora lo veremos con un ejemplo completo para que te quede perfectamente claro.
Pongamos que queremos hacer un componente que muestre un párrafo en un espacio reducido de la página. El párrafo
tiene mucho texto así que a veces se puede recortar. Pero también queremos que el usuario pueda verlo entero si lo
requiere, pulsando un botón para evitar ese recorte.
Nota: Esta tarea es bastante simple como para hacer un único componente, quizás no es el mejor ejemplo, pero
piensa en una aplicación pequeña o mediana, la cantidad de subtareas que puede tener. Cada una de ellas se
encapsula en un componente y eso permite que su complejidad sea pequeña, facilitando el desarrollo, pero sobre
todo el mantenimiento, y ubicando perfectamente cada cosa en su sitio.
Para esta tarea podemos pensar en dos componentes distintos. Uno que se encargue únicamente del recorte de la
cadena y otro que se encargue de la interacción con el usuario, permitiendo captar el evento de recorte o despliegue del
párrafo cuando se pulsa el correspondiente botón. Quebrar esta tarea en dos componentes todavía es una solución más
acertada cuando pensamos que ya existe el componente de romper una cadena, porque lo tenemos desarrollado ya en
un mencionado artículo anterior.
desarrolloweb.com/manuales/polymer.html Página 50
Manual de Polymer
<template>
<p>
<rompe-cadena str="{{cadena}}" len="{{longitud}}"></rompe-cadena>
<iron-icon icon="{{icono}}" on-tap="mostrarRecortar"></iron-icon>
</p></template>
Como ves, unos componentes incluyen a otros y así se va generando ese árbol de componentes que son capaces de
hacer funcionar una aplicación completa.
En este caso tenemos el componente rompe-cadena, que se encarga de romper una cadena a una longitud dada. Si te
fijas, la cadena y la longitud no se entregan de manera literal, sino que las tenemos bindeadas a dos propiedades del
componente padre ("cadena" y "longitud").
Luego, en vez de un botón propiamente dicho, hemos usado un icono, del catálogo de elementos de Polymer. Lo divertido
es que la imagen del icono que se debe mostrar no se especifica tampoco, sino que está bindeada la propiedad "icono".
Aquí tienes otro ejemplo de interoperabilidad entre componentes y lo hacemos así simplemente para que, cuando el
párrafo está expandido se muestre un icono de contraer y cuando el párrafo está contraído se muestre un icono distinto.
Bueno, en realidad es el mismo elemento iron-icon, solo que indicando valores distintos al atributo "icon", con lo que
cambiará el aspecto.
Nota: Ten cuidado cuando uses elementos del catálogo de componentes de Polymer, puesto que los tendrás que
importar debidamente y haberlos descargado previamente con Bower. Esto ya lo vimos al tratar los capítulos de
usar elementos de Polymer.
Hay otra cosa importante en este template y es que el icono tiene un evento. No hemos llegado a hablar de eventos
todavía, pero básicamente "on-tap" nos sirve para detectar un "click" o un "tap" (clic de dispositivos touch) sobre ese
icono. En ese evento se invoca un método del propio componente llamado mostrarRecortar() que veremos enseguida.
Ahora veamos cómo hemos registrado este componente, en el script Javascript. Aunque mostrarmos el listado completo,
nos centraremos primero en la declaración de propiedades.
Polymer({
is: "mostrar-recortar",
properties: {
cadena: String,
longitud: {
type: Number,
value: 20
},
longitudDefault: Number,
icono: {
desarrolloweb.com/manuales/polymer.html Página 51
Manual de Polymer
type: String,
value: 'remove'
}
},
ready: function() {
if(this.longitud == 0){
this.icon = 'add';
}
},
mostrarRecortar: function() {
if(this.longitud > 0) {
this.longitudDefault = this.longitud;
this.longitud = 0;
this.icono = 'add';
} else {
this.longitud = this.longitudDefault;
this.icono = 'remove';
}
}});
cadena: es el texto completo del párrafo. No lo inicializo a valor alguno por defecto, porque este componente sin
que se le entregue el párrafo a mostrar no tiene sentido utilizarlo.
longitud: es la longitud del recorte cuando está contraido el texto del párrafo. Valor predeterminado es 20. Esta
propiedad es la que se bindea sobre el componente "romper-cadena" para decirle qué longitud se debe mostrar en
cada momento.
longitudDefault: este dato, que tampoco inicializo, lo he creado para guardar el valor indicado como longitud por
defecto. Como el campo longitud será variable, en algún lugar debo de almacenar la longitud de recorte, para no
perderla cuando asigne otro valor a la propiedad "longitud".
icono: esta es la propiedad que usaré para guardar el valor del icono, inicialmente es un icono que indica
"remove", que usaré porque entiendo que el texto pueda aparecer con su tamaño completo inicialmente.
ready: este método es uno de los del ciclo de vida de los componentes de Polymer. Cuando el componente esté
listo e inicializado mirará si la longitud > 0, porque entiendo que en ese caso quiero mostrar un icono en concreto
y no el otro con el que hemos inicializado la propiedad "icono". (Ten en cuenta que he entendido en este
componente que si la longitud es cero, entonces se mostrará el texto completo sin recorte).
mostrarRecortar: este es el corazón de la funcionalidad del componente. Es el método que se invoca con el
evento "tap" sobre el icono. Si detecta que está expandido se contrae y si detecta que está contraido se expande.
Esto lo consigo vigilando la propiedad longitud (si es igual a cero es que está expandido). En cualquiera de los
casos caso simplemente se modifican las propiedades necesarias para que todo reaccione como debe. Haz un
breve seguimiento al código y creo que lo entenderás bien.
Como las propiedades están bindeadas al template, en los métodos que orquestan el funcionamiento del componente
simplemente me dedico a cambiar sus valores. Además, lo interesante en este ejemplo es que algunas propiedades
viajan hacia los componentes hijo, produciéndose la interoperabilidad.
Nota: Es importante mencionar con respecto al componente rompe-cadena que hicimos en el artículo sobre el
Registro de propiedades que hemos tenido que hacer una pequeña modificación para adaptarlo a estas necesidades
y es el hecho de evaluar también si la longitud es igual a cero, en cuyo caso hemos dicho que no queríamos realizar
recorte.
calculaRecorte(len, str){
if (str.length <= len || len == 0) {
return str;
}
var recortada = str.substr(0, len);
return recortada.substr(0, Math.min(recortada.length, recortada.lastIndexOf(' '))) + '...';
desarrolloweb.com/manuales/polymer.html Página 52
Manual de Polymer
El código completo de los componentes que hemos visto en este artículo lo puedes encontrar en GitHub, en el repositorio
del Manual de Polymer.
En este artículo hemos visto bastante información sobre cómo bindear datos entre componentes, pero todavía nos
quedan cosas interesantes que analizar con detalle, como es el caso del bindeo de datos desde los hijos a los padres, que
veremos en el próximo capítulo del Manual de Polymer.
En el ejemplo del artículo anterior hemos hecho uso de binding entre componentes, pero solo hemos enviado datos del
padre hacia el hijo. Podría darse el caso que desees también bindear y enviar datos desde el hijo hacia los padres.
Esta parte en Polymer no se hace automáticamente, puesto que tendremos que configurar el hijo explícitamente para
decirle que, en caso de binding en una propiedad, se envíen los datos hacia el padre. Dicho de otra manera, necesitamos
decirte a Polymer si deseamos que se notifique al padre de los cambios realizados en propiedades en el hijo.
Declaración notify
Que los datos bindeados viajen de los componentes hijos a los padres se consigue por medio de una declaración que
todavía no habíamos visto en el Manual de Polymer. Es el atributo "notify" que usamos al declarar propiedades de
componentes.
Notify de manera predeterminada vale "false", produciendo que no se notifique a los padres. Es decir, si se
cambian en el hijo propiedades que nos vienen bindeadas del padre, no se enviarán los nuevos valores.
Si declaramos la propiedad y asignamos "true" a su valor "notify" entonces sí que viajará el dato actualizado desde
el hijo al padre.
Para hacer un ejemplo de este caso hemos recurrido al mismo caso que se ha solucionado anteriormente. Volvemos al
ejemplo del párrafo que puede estar expandido o colapsado, pero le vamos a aplicar unas modificaciones.
desarrolloweb.com/manuales/polymer.html Página 53
Manual de Polymer
Nota: La arquitectura sigue siendo la misma y la funcionalidad idéntica, así que estos cambios podemos decir que
son solo "por capricho", puesto que nuestro componente ya funcionaba perfectamente. El motivo es puramente
didáctico.
Componentes no representacionales
El cambio fundamental en este ejemplo es que nuestro componente romper-cadena no mostrará ninguna cadena. Es un
componente que no tiene representación alguna en el template.
Los componentes no-representacionales son comunes en el desarrollo basado en Web Components. Son componentes
que no muestran ninguna información, sino que simplemente resuelven alguna necesidad sin producir salida en la
página. Son generalmente "helpers", ayudantes para llevar a cabo ciertas tareas.
En nuestro ejemplo actual hemos alterado el componente romper-cadena, que ya vimos en el artículo Registro de
propiedades, para que no tenga representación alguna.
Simplemente hemos quitado el TEMPLATE, de modo que no pintará nada en la página cuando se incluya en otros
componentes.
Nota: Los códigos completos de los componentes que vamos a ver en este artículo están en este enlace a Github.
Componente rompe-cadena-no-representacional
En este componente es donde hemos quitado toda la presentación del template. Pero hay un cambio muy importante que
debemos mostrar.
Como ahora no representa él mismo la cadena recortada, tendrá que comunicársela al padre. Esto es sencillo de
conseguir con la propiedad "notify". La propiedad que tiene que notificarse al padre es "recorte" que ahora nos queda así:
recorte: {
type: String,
computed: 'calculaRecorte(len, str)',
readOnly: true,
notify: true}
Declaración readOnly
Además aprovechamos para ver en funcionamiento otra de las posiblidades al declarar propiedades de componentes, que
es "readOnly". En este caso es muy interesante porque la propiedad de recorte es algo que calcula el componente
"rompe-cadena-no-representacional" y que no se debería modificar desde fuera, porque podría producirse un mal-
funcionamiento del componente.
Esta propiedad declarada como readOnly no es que sea una constante, pues dentro del componente dueño de la
propiedad la puedo modificar. Simplemente indica que desde fuera no la podrán "setear".
Ojo, como verás a continuación sí se pueden bindear propiedades desde otros componentes a propiedades readOnly,
simplemente, aunque se cambie el valor desde fuera, no se permitirá la acción por haber sido declarada como de solo-
lectura.
desarrolloweb.com/manuales/polymer.html Página 54
Manual de Polymer
Componente mostrar-recortar-representacional
Para hacer este ejemplo hemos realizado sobre todo unos cambios en el template del componente mostrar-recortar
original. Básicamente, como el componente romper-cadena-no-representacional no muestra la cadena en cuestión, la
vamos a tener que mostrar nosotros en el template. Nos quedaría así:
<template>
<rompe-cadena-no-representacional str="{{cadena}}" len="{{longitud}}" recorte="{{recorte}}"></rompe-cadena-no-representaci
<p>
{{recorte}}
<iron-icon icon="{{icono}}" on-tap="mostrarRecortar"></iron-icon>
</p></template>
El resto del componente es exactamente igual que lo que teníamos en el artículo anterior.
Esperamos que lo puedas seguir, recuerda ver el código en GitHub en el repositorio del manual y hacer tus propias
pruebas y prácticas para seguir afianzando los conocimientos.
desarrolloweb.com/manuales/polymer.html Página 55
Manual de Polymer
}
},
mostrarRecortar: function() {
if(this.longitud > 0) {
this.longitudDefault = this.longitud;
this.longitud = 0;
this.icono = 'add';
} else {
this.longitud = this.longitudDefault;
this.icono = 'remove';
}
}
});
</script></dom-module>
desarrolloweb.com/manuales/polymer.html Página 56
Manual de Polymer
Parte 5:
Herramientas indispensables para
desarrollar con Polymer
Conoceremos algunas herramientas esenciales para facilitar el desarrollo de
aplicaciones web basadas en Polymer.
En este artículo vamos a dar una pequeña receta para iniciar un nuevo proyecto con Polymer Starter Kit. Veremos que
usando Yeoman se facilita extremamente la labor. Iremos dando los pasos progresivamente con explicaciones y consejos.
Primero que nada, tendremos que ponernos en antecedentes, por si acaso no todos los lectores conocen las herramientas
con las que vamos a trabajar.
Polymer: es una librería para el desarrollo con el estándar Web Components. Te permite desarrollar rápidamente
custom elements, que son como etiquetas HTML personalizadas.
Bower: es un gestor de paquetes que se usa para descargar y mantener actualizadas las dependencias de un
proyecto web.
Yeoman: es una serie de puntos de inicio, con estructuras de carpetas y archivos con código que te pueden servir
de base para comenzar proyectos, o todo tipo de piezas de software que realizas habitualmente al desarrollar un
sitio web o aplicación. Básicamente, mediante comandos de consola, te ahorra muchas tareas repetitivas en el
desarrollo, generando lo que se conoce como "scaffolding".
Gulp: es una herramienta para la automatización de tareas de todo tipo relacionadas con el desarrollo web.
Optimiza archivos, compacta, minimiza, procesa preprocesadores... y todo lo que se te ocurra! Te ahorra mucho
trabajo con tareas repetitivas que no necesitarás realizar nunca más manualmente.
desarrolloweb.com/manuales/polymer.html Página 57
Manual de Polymer
Polymer es una librería que generalmente te descargarás para aquel proyecto donde la necesitas. Lo haces con Bower y
suponemos que ya lo conoces. Si no, comienza por el artículo donde explicamos Bower.
Yeoman lo instalas generalmente de manera global en tu ordenador. Lo haces con el comando npm:
npm install -g yo
Encontrarás cuatro recetas útiles, que instalas con el comando "yo" (abreviación de Yeoman) y el nombre de la receta,
por ejemplo:
yo polymer
Las recetas, o generadores, que obtienes dedicados a Polymer son los siguientes:
polymer
Esta receta es la que inicia un nuevo proyecto basado en Polymer Starter Kit. En seguida hablaremos de ella.
polymer:element (o polymer:el)
Esta receta comienza un nuevo elemento de Polymer., lo coloca en la carpeta de elements (app/elements) y te pregunta
si deseas incluir el import en el archivo elements.html
polymer:seed
Este sirve para que puedas crear un elemento de Polymer, con todo lo necesario para que puedas distribuirlo vía Bower.
Entre todas las cosas que te ofrece encuentras el archivo para hacer el demo, el bower.json para distribuirlo, una página
de ayuda del componente
polymer:gh
Te genera el sistema para publicar en "github pages" el contenido de trabajo con el elemento.
La página del proyecto de recetas Yeoman, donde encontrarás bastante información sobre estos generadores para
Polymer, la tienes en Github: https://github.com/yeoman/generator-polymer
desarrolloweb.com/manuales/polymer.html Página 58
Manual de Polymer
2.- Abres una ventana de terminal y por línea de comandos te sitúas dentro de la carpeta de proyecto que acabas de
crear
yo polymer
En este punto Yeoman se pondrá a trabajar para instalar un nuevo proyecto basado en el PSK. Pero antes te hará un par
de preguntas sencillas sobre si quieres que te instale un sistema para testing de componentes y si quieres que te adjunte
en las carpetas unos documentos con diversas ayudas ante operativas comunes en el trabajo de un sitio con Polymer.
4.- Nuestro sitio ya está generado. Te recomendamos echar un vistazo a las carpetas del proyecto. Más adelante daremos
una descripción completa de cada cosa, pero de momento es interesante que repares que existe una carpeta llamada
"app" que es donde está toda la aplicación. las carpetas que están por fuera de "app" contienen cosas importantes, pero
que no formarían parte de tu sitio web.
Dentro de "app" encontrarás el index.html que es el punto de entrada a esta aplicación. Recuerda que es una aplicación
SPA (single page application) por lo que solo está ese archivo html como página y todas las secciones del sitio se
muestran sobre ese mismo fichero, intercambiando lo que serían las vistas.
5.- Ahora podemos poner en marcha el proyecto y verlo en un navegador. Existen una serie de tareas Gulp para realizar
esto de una manera cómoda. solo tienes que correr, desde la carpeta de tu proyecto, el siguiente comando.
gulp serve
Eso realizará toda una serie de acciones que describiremos más adelante y a continuación abrirá directamente en tu
navegador la página donde está desplegada la aplicación durante la etapa de desarrollo.
Si no ocurriese nada observa que al ejecutar "gulp serve" aparece un mensaje donde se indica la URL donde debes
acceder para visualizar el sitio, tanto desde tu ordenador local como desde otro ordenador o dispositivo en tu red local.
6.- Desplegar en un servidor. Realmente esto no es una tarea que tengas que hacer ahora, pero seguramente te lo estés
preguntando, o te lo preguntes en breve. Para desplegar la aplicación no se sube la carpeta "app" a un servidor web. Esos
son solo los archivos fuente de tu proyecto. En realidad lo que se sube es la carpeta dist, que contendrá los archivos a
distribuir en el entorno de producción, correctamente optimizados para poder distribuirse de la mejor manera en un
entorno web. Inicialmente esa carpeta estará prácticamente vacía, pero puedes generar tales archivos a través de tu
código fuente con otra tarea de Gulp. Simplemente usas el comando:
gulp
7.- Inicia Git. Otra cosa que deberías hacer ahora que comienza tu proyecto es iniciar el repositorio Git. Observa que
dentro del proyecto hay un archivo llamado ".gitignore" (oculto en Mac y Linux por comenzar por ".") que indica que este
proyecto ya está pensado para gestionar sus versiones con Git.
git init
Con esto tienes la información que necesitas para poder iniciarte en el Polymer Starter Kit, todo un regalo de buenas
prácticas para el desarrollo con Web Components y Polymer.
desarrolloweb.com/manuales/polymer.html Página 59
Manual de Polymer
En este artículo vamos a hablar de una herramienta importante para el desarrollo de Web Components. Básicamente
permite optimizar un proyecto para su publicación en Internet, de modo que un sitio web basado en componentes tenga
mayor desempeño.
Es una herramienta construida con NodeJS por el equipo de Polymer, aunque la podrías usar para cualquier proyecto que
use Web Components. El repositorio en Github de Vulcanize lo encuentras en: https://github.com/Polymer/vulcanize
Es muy fácil de utilizar, como veremos a continuación. Pero antes de comenzar vamos a explicar el motivo de la
existencia de estas herramientas de producción.
Esto es clave en el desarrollo con Polymer (y extensible a cualquier otra fórmula de desarrollo basado en Web
Components) puesto que generas decenas, o centenas, de archivos con código para cada uno de los elementos de una
aplicación. A la hora de desarrollar nos viene muy cómodo tener los componentes separados por ficheros, porque así
sabremos dónde está cada cosa, pero a la hora de publicar el proyecto ya no es una situación deseable.
Aquí es donde entra el denominado proceso de vulcanizado, que básicamente es unir todos los archivos de los
componentes en un único archivo con todo el código. Obviamente no lo haces a mano, sino con una herramienta llamada
"Vulcanize"
Nota: Con la próxima llegada de HTTP2 este tipo de herramientas quedarán obsoletas porque el protocolo no
penalizará que el servidor envíe los múltiples archivos de los que consta una página web.
Instalación de Vulcanize
desarrolloweb.com/manuales/polymer.html Página 60
Manual de Polymer
La herramienta se instala mediante npm, siendo una recomendación instalarla de manera global. Usamos el comando:
Usando Vulcanize
Posteriormente podremos usar la herramienta mediante el comando "vulcanize". Básicamente le tenemos que indicar un
punto de entrada y un archivo de salida.
El vulcanizado de elementos recorrerá los archivos importados que haya en el archivo de entrada indicado (en ese caso el
"index.html") y los irá uniendo. Escribirá el resultado de su concatenación en el archivo de salida indicado (en este caso
"elementos.html").
Nota: Es interesante comentar que este proceso recorre los imports de la especificación de Web Components que se
estén usando en el proyecto en un momento dado, no todas las librerías que tengas en una carpeta. Puede darse el
caso que hayas instalado un proyecto una cantidad enorme de componentes, pero que solo hayas usado
verdaderamente unos pocos. El vulcanizado sólo unirá los HTML Imports que se encuentren en el código de tu
archivo de entrada y en el código de todos los archivos importados, de manera recursiva.
Además existen varias opciones que permiten personalizar el funcionamiento del vulcanizado. Una muy útil es la
posibilidad de indicarle una ruta. Esto es importante porque a veces el proceso de despliegue de la aplicación incluye un
cambio de estructura de carpetas.
Esto irá a buscar el archivo de origen "index.html" a "app/index.html" y el archivo vulcanizado lo dejará en la ruta
"dist/elements/elements.html".
Esta opción es importante porque a veces los componentes tienen archivos "assets", como imágenes que no queremos
que se rompan. Las rutas de todos estos archivos las colocará absolutas a la raíz del web server, teniendo en cuenta que
"app" sería esa raíz (dado el anterior comando).
Lo que sí tiene es una opción para quitar comentarios, que elimina todos menos aquellos que comienzan por @license.
Como ya comentamos en el artículo del Polymer Starter Kit al lanzar el comando "gulp" se desatan todas las tareas para
el despliegue del proyecto, con todas las herramientas frontend orquestadas por Gulp, entre las que se incluye el propio
sistema de vulcanizado.
desarrolloweb.com/manuales/polymer.html Página 61
Manual de Polymer
Después de lanzar ese proceso, verás que en la carpeta "dist/elements" hay un solo archivo que son todos los elementos
después de pasar por vulcanize. De nuevo, es una razón adicional para usar Polymer Starter Kit para el arranque tu
proyecto.
desarrolloweb.com/manuales/polymer.html Página 62