polymer: 7. propiedades

La definición de propiedades y cómo lanzar funciones cuando cambian

Vincent Van Gogh

archivado en: JavaScript / 25 febrero, 2016 / taller:

Ya se llame polymer, angular, backbone o ember, cualquier frame en javaScript es antes que nada una forma de definir objetos y organizar la relación que mantienen entre sí. Y un «objeto» solo es un conjunto de métodos -de funciones- y propiedades, esto es, de variables. Es decir, de cosas que hacen cosas y de cosas que tiene un valor.

var miObjeto = {

miPropiedad: 'azul',

otraPropiedad: 'amarillo',

miMetodo: function() {

// mezclar propiedades

}

}

Ya hemos visto cómo podemos definir métodos a los componentes de polymer, que no son sino objetos, en esta entrada trataré  las propiedades y para eso vamos a preparar un componente que sea un formulario capaz de validarse a sí mismo. Tendrá dos campos, uno para el nombre de usuario y otro para su correo, y un botón enviar. Hasta que los dos campos no estén escritos correctamente, el botón permanecerá deshabilitado con el atributo disabled.

Un poco de html

Con una miaja de estilos ahora que ya sabemos cómo funcionan en polymer, el armazón básico de nuestro componente podría ser algo así.

form-auto.html

<dom-module id="form-auto">

<template>

<style>

:host .form-element {

margin: 0.5em;

}

:host .form-button {

margin: 0.5em;

padding: 0.5em;

background: #ededed;

border: 1px solid #ccc;

}

</style>

<form>

<div class="form-element">

<input id="user" type="text" placeholder="User">

</div>

<div class="form-element">

<input id="email" type="text" placeholder="Email">

</div>

<button id="sendButton" class="form-button" disabled>Send</button>

</form>

</template>

<script>

Polymer({

is: 'form-auto'

});

</script>

</dom-module>

Traducido ya a html renderizado por un navegador, nos debería quedar algo así.

wc-form-00

Bueno, pues con todo listo, vamos al lío ^^.

Definir propiedades

Las propiedades de un web component polymeresco se definen en un (sub)objeto denominado precisamente properties. Por ejemplo, así añadiríamos dos propiedades a nuestro formulario que nos servirán para controlar si ya se ha escrito algo y si ese algo es correcto. Y también vamos a poner un console en el evento ready para comprobar por consola que el objeto tiene esas dos propiedades.

<script>

Polymer({

is: 'form-auto',

properties: {

isPristine: true,

isValid: false

},

ready: function() {

console.log(this.properties);

}

});

</script>

Además, en cada propiedad podemos matizar varios detalles:

1. type: El tipo que es (literal, booleano...). Los valores que admite son Boolean, Date, Number, String, Array y Object.

2. value: El valor por defecto, que puede ser un literal, un número, un valor booleano o una función, en cuyo caso es lo que se devuelve en el return, como veremos un poco más adelante.

3. reflectToAttribute: true o false para indicar si la propiedad debe incluirse como atributo en el tag principal del componente. El camelCase se convierte en guion y el valor se convierte en literal sea cual sea el punto de partida.

4. readOnly: true o false para indicar si se puede o no modificar.

5. notify: este valor, que puede ser true o false, está relacionado con el «data binding», que es un tema que trataré en la próxima entrada.

6. computed: es una propiedad read only que sirve para definir el valor cuando es resultado de un cálculo en el que intervienen otras propiedades.

7. Observer: el nombre del método que se invocará cuando la propiedad cambie de valor.

Veamos cómo funcionan algunos de estos matices aplicándolos a nuestro formulario.

Añadimos un id

Aunque es un poco tontunaka, como creo que aclarará varias ideas, vamos a añadir una propiedad a nuestro componente que sea su id y para eso, además de indicar que queremos que se refleje en el tag del componente, lo que haremos será definir su valor como resultado de una función en la cual comprobaremos si el elemento tiene o no un id definido. Si no lo tiene, lo calcularemos a partir del timestamp.

...

properties: {

isPristine: true,

isValid: false,

id: {

type: String,

readOnly: true,

reflectToAttribute: true,

value: function() {

var _id = this.getAttribute('id') || Date.now();

return _id;

}

}

}

...

...

Ale op, nuestro componente ya tiene un id autogenerado:

wc-form-01

 

Recordemos que para definir atributos en el tag del componente también contamos con los hostAttributes.

Desde los atributos

Al igual que desde las propiedades podemos definir atributos, desde estos podemos definir propiedades. La única regla que debemos tener en cuenta es que el guion de los atributos se convierte en camelCase en la propiedad.

Para que se entienda añadimos dos propiedades más a nuestro componente, una para el nombre de usuario y otra para el correo:

userName: String,

eMail: String,

Y definimos una de ellas desde el tag del componente:

<form-auto user-name="foo"></form-auto>

Así, por ejemplo, podríamos modificar el valor del input userName si nos llega desde el tag (ya veremos cómo hacerlo de forma más sencilla mediante el Data binding).

...

ready: function() {

if ( this.userName ) {

this.$.user.value = this.userName;

}

}

...

Desde el tag también podemos pasar jasonakos y arrays. Basta con que tengan su reflejo como propiedad camelCaseizada en la definición del componente.

<form-auto user-name="foo" json-demo='[{"bazinga":0}, {"bazinga":1}]'></form-auto>

Observer

Para que entendamos mejor cómo funcionan los observer, vamos a refactorizar el componente de una manera un tanto enrevesada y poco óptima, pero espero que didáctica.

Añadimos dos eventos a los inputs que llamarán a sendas funciones, en las cuales asignamos el valor de la propiedad respectiva al valor que tenga en ese momento el input. En código queda más claro:

....

<form>

<div class="form-element">

<input id="user" type="text" placeholder="User" on-blur="_setUser">

</div

<div class="form-element">

<input id="email" type="text" placeholder="Email" on-blur="_setEmail">

</div>

...

_setUser: function() {

this.userName = this.$.user.value;

},

_setEmail: function() {

this.eMail = this.$.email.value;

},

...

Y ahora refactorizamos la declaración de las dos propiedades para asignarles un observer que invocará a una función...

...

userName: {

type: String,

observer: '_checkInputs'

},

eMail: {

type: String,

observer: '_checkInputs'

},

...

Y en esta función, que será invocada cada vez que la propiedad cambie de valor, miramos si los inputs están rellenados y si el email es un correo (la comprobación es así de sencilla por motivos didácticos) para habilitar o no el botón de envío.

...

_checkInputs: function() {

if ( this.userName && this.eMail && this.eMail.indexOf('@') !== -1 ) {

this.$.sendButton.removeAttribute('disabled');

} else {

this.$.sendButton.setAttribute('disabled', true);

}

}

...

Esto empieza a ponerse divertido, pero hay una nota discordante en este algoritmo y es que resulta bastante molesto tener que repetir en las dos propiedades la misma invocación. Don panic!, pues para estos casos contamos con observers, que nos permite agrupar propiedades cuyos observer lanzan la misma función. Refactorizamos pues el código para dejarlo más ordenado:

...

properties: {

userName:String,

eMail: String,

},

observers: [

'_checkInputs(userName, eMail)'

],

...

Para terminar de ver cómo trabajan los observer y ver cómo optimizar su definición con wildcards recomiendo el polycast Supercharged Observers!

Bueno, en lo que atañe a las propiedades, nos queda por ver el notify y los casos complejos de observación, los que están relacionados con arrays y objetos, pero eso lo trataré en la próxima entrada, cuando hable del data binding. De momento lo dejo aquí.

el ejemplo de esta entrada está en git

|| Tags:

valoración de los lectores sobre polymer: 7. propiedades

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 5 sobre 5 (2 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Los comentarios están cerrados.