Este artículo debió llamarse "Especie de introducción a AngularJS". Es decir, estuve
trabajando por mucho tiempo en una aplicación con AngularJS como framework: Fue una muy buena experiencia, y ha sido mi culpa empezar a aprender algo que años antes ya se sabía
iba a quedar obsoleto por rediseño. Todos
los cambios me superan: Claro que así descritos parecen una mejora, pero el sólo hecho de cambiar a TypeScript me hizo repensar desde cero toda la aplicación.
Así que reconsideré a Polymer: Esta basado en
webcomponents, algo que ya había alcanzado a vislumbrar con AngularJS 1.5. Webcomponents aspira a ser el futuro de la web, bueno, así que veremos que tal se comporta en el presente.
Para instalarlo en Fedora, bastará con correr los siguiente comandos como root. Para npm,
-g implica global, con lo que se supone que otros usuarios en el sistema podrían usar las herramientas así instaladas:
dnf install npm
npm -g install bower
npm -g install polymer-cli
Luego seguimos las
indicaciones que nos hace la gente de polymer. Desde consola, como cualquier usuario disponible en el sistema y ubicados desde cualquier parte que querramos (Preferentemente no "cualquier" parte), ejecutamos lo siguiente:
mkdir polymer-muestra-inicial
cd polymer-muestra-inicial/
polymer init --name polymer-2-application
Donde
--name permite seleccionar la plantilla inicial para nuestro proyecto.
polymer-2-application arranca con poco código, lo que es conveniente para aprender lo más posible.
polymer init --name polymer-2-application
info: Running template polymer-init-polymer-2-application:app...
? Application name polymer-muestra-inicial
? Main element name polymer-muestra-inicial-app
? Brief description of the application Breve descripción de mi persona
A continuación, se instalan todos los paquetes necesarios para nuestra aplicación mediante
bower, y es mediante él que debemos agregar nuevas dependencias.
En este momento, podemos probar lo que tenemos hasta ahora (Casi nada a decir verdad) ejecutando desde consola:
polymer serve --open
No subestimen este comando: Incluso permite servir contenido como HTTPS.
Ahora empezamos la introducción propiamente dicha:
Aclaro que a este momento sigo sin pensar en una estructura de directorios para el código, así que voy a separarlo en componentes tanto como sea posible.
mkdir -p src/componentes/entradas
cd src/componentes/entradas
Además, voy a trabajar modificando el componente que se ha creado originalmente para esta aplicación:
polymer-muestra-inicial-app, no tanto por añorar mi época con AngularJS, sino por aprovechar todo el conocimiento previo de dicha época.
Así, creamos el fichero
src/componentes/entradas/vt-entrada.html, que define un input casi sin modificación alguna, con el siguiente contenido
<link href="../../../bower_components/polymer/polymer-element.html" rel="import"></link>
<dom-module id="vt-entrada">
<template>
<style>
:host {
display: block;
}
</style>
<input type="text" value="{{contenido}}" />
</template>
<script>
class VtEntrada extends Polymer.Element {
static get is() {
return 'vt-entrada';
}
static get properties() {
return {
contenido: {
type: String,
}
}
}
}
window.customElements.define(VtEntrada.is, VtEntrada);
</script>
</dom-module>
A ver, para explicaciones más detalladas las teoría. Desde aquí, sin embargo, podemos decir:
- Esta es casi, casi la forma en que se define un webcomponent nativo al día de hoy: Dentro de <template></template> tenemos el HTML de toda la vida; dentro de <script></script> la definición de nuestro componente. Todo dentro de <dom-module>.
- properties define las propiedades de este componente, en resumen, las variables con las que nos relacionamos con otros componente y que controlamos mediante código. En realidad, extenderse en la teoría de este tema con la documentación oficial es un muy buen primer paso a tomar.
- El estilo CSS definido dentro de <style> se circunscribe a este componente, mediante una técnica llamada DOM Shadow que hoy en día ya sirve para muchas otras cosas además de encapsular CSS (Igual nace por esta necesidad específica)
Ahora modificamos el componente que se venía de la plantilla, básicamente haciendo un import y usando nuestro componente. Al final se tiene que ver de la siguiente forma:
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="/src/componentes/entradas/vt-entrada.html">
<dom-module id="polymer-muestra-inicial-app">
<template>
<style>
:host {
display: block;
}
</style>
<h2>Hello [[prop1]]!</h2>
<vt-entrada contenido="Configurado desde plantilla padre"></vt-entrada>
</template>
<script>
/**
* @customElement
* @polymer
*/
class PolymerMuestraInicialApp extends Polymer.Element {
static get is() { return 'polymer-muestra-inicial-app'; }
static get properties() {
return {
prop1: {
type: String,
value: 'polymer-muestra-inicial-app'
}
};
}
}
window.customElements.define(PolymerMuestraInicialApp.is, PolymerMuestraInicialApp);
</script>
</dom-module>
Al verlo en la navegador, tenemos algo como esto:
Ahora hacemos que esta introducción valga la pena:
Visto así, polymer casi nos parece un sistema de plantillas estático, así que para despertar el interés haremos unos cambios en nuestro componente
vt-entrada: Los cambios se realizan en la plantilla, agregando un
<p></p> cuyo contenido se hace refencia a la propiedad
contenido de nuestro componente.
Por otra parte, vamos a cambiar el data binding de nuestro <input> para que funcione en forma bidireccional: En lugar de
contenido, ahora será
contenido::input.
Lo último a resaltar es que tenemos dos forma de hacer los binding: En una vía mediante llaves y bidireccional mediante corchetes. Esto es otro tema bastante complicado en el que se debería extender con
la documentación oficial. Al final, nuestro componente debe verse de la siguiente forma:
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<dom-module id="vt-entrada">
<template>
<style>
:host {
display: block;
}
</style>
<input type="text" value="{{contenido::input}}">
<p> Este es nuestro contenido escribiente: [[contenido]]</p>
</template>
<script>
class VtEntrada extends Polymer.Element {
static get is() {
return 'vt-entrada';
}
static get properties() {
return {
contenido: {
type: String,
}
}
}
}
window.customElements.define(VtEntrada.is, VtEntrada);
</script>
</dom-module>
Lo vemos de la siguiente forma en el navegador:
Y sí, el contenido se actualiza conforme se escribe en la caja de texto. Así como que ya dan más ganas de trabajar con esto.
Supongo que para una breve introducción ya está.