Client Side Meteor 5. Formularios automáticos con Autoform


En la entrada anterior dejé la app Contactos completamente funcional. El componente principal de dicha app es un formulario que permite insertar Contactos. Este formulario fue escrito manualmente, por lo que en esta entrada haré uso de un paquete que lo genere de forma automática.

Autoform

Es un paquete especializado en el trato de formularios en aplicaciones Meteor. Permite crear un esquema y, a partir de él, validar campos de formularios de forma automática.

Aunque Autoform se puede utilizar para cualquier tipo de formulario, su excelencia radica en lo fácil que es crear formularios para realizar acciones CRUD sobre colecciones.

Instalación

Para instalar este paquete, sitúate sobre tu proyecto (en este caso la app Contactos) mediante la consola:

meteor add aldeed:autoform aldeed:collection2

Por defecto, a los formularios que creas con este paquete se le aplican clases Bootstrap. Como no usamos este framework en la app Contactos, debemos modificar este comportamiento instalando un paquete que se ajuste a Ionic:

meteor add meteoric:autoform-ionic

Modo de uso

Para aplicar las bondades de Autoform sobre el formulario de insertar Contactos, se debe crear un esquema para que se validen los campos de forma automática. Cuando instalé el paquete aldeed:autoform se instaló además como una dependencia aldeed:simple-schema, el cual me permitirá realizar dicha tarea. Nota además cómo le asigno el esquema directamente a la colección. Esto es posible gracias al paquete collection2, que fue instalado junto con autoform:

// fichero client/colecciones.js
Contactos = new Ground.Collection('contactos', {connection:null});

Contactos.attachSchema(new SimpleSchema({
    nombre    : {
        type    : String,
        label   : 'Nombre',
        autoform: {
            placeholder : 'su nombre'
        },
        max     : 200
    },
    apellido: {
        type    : String,
        label   : 'Apellidos',
        autoform: {
            placeholder : 'sus apellidos'
        },
        max     : 200
    }
}));

Con el código anterior se puede cambiar el anterior template NuevoContacto a:

// fichero client/contactos/nuevo_contacto.js

<template name="NuevoContacto">
  {{#ionModal customTemplate=true}}
    {{#autoForm collection="Contactos" id="contacto-nuevo" type="insert"}}
      <div class="bar bar-header bar-stable bar-positive">
        <button data-dismiss="modal" type="button" class="button button-clear">Cancelar</button>
        <h2 class="title"> Crear contacto </h2>
        <button type="submit" class="button button-clear">Aceptar</button>
      </div>
      <div class="content has-header overflow-scroll">
        {{> afQuickFields }}
      </div>
    {{/autoForm}}
  {{/ionModal}}
</template>

Las dos instrucciones más importantes aquí son:

  1. La declaración del formulario con autoform utilizando bloques de contenido para personalizar la estructura interna del formulario.
  2. La inclusión del template afQuickFields para incluir todos los campos definidos en la colección.

Normalmente no es necesario incluir dentro los botones Aceptar y Cancelar. Pero en este caso, se debe ajustar el maquetado a un modal Ionic, con sus respectivas clases y etiquetas.

Con lo anterior realizado, la lógica del JavaScript asociado al template no es necesaria, por lo que puedes cambiar ese fichero con el siguiente contenido:

// fichero client/contactos/nuevo_contacto.js

AutoForm.hooks({
  'contacto-nuevo': {
    onSuccess: function (operation, result, template) {
      IonModal.close();      
    },
    onError: function(operation, error, template) {
      alert(error);
    }
  }
});

En lugar de crear helpers y eventos sobre el template, se utiliza el objeto global AutoForm y se definen las funciones a ejecutar cuando se tuvo éxito o fracaso en la operación Insertar del formulario.

El formulario Edición

Con la implementación anterior se perdió la funcionalidad de Editar un Contacto. No obstante, se puede recuperar fácilmente con AutoForm.

En el template Contacto, indica que al dar clic sobre el botón Editar, se muestre un template llamado EditarContacto y pásale el id del contacto en cuestión:

// fichero client/contactos/lista_contactos.html

<template name="Contacto">
    <p>
        Nombre completo: {{ nombre }} {{ apellidos }}
        <button class="edit" data-ion-modal="EditarContacto" data-id="{{ _id }}">
            e
        </button>
        <button class="del">
            x
        </button>
    </p>
</template>

Tal template no existe, por lo que lo puedes crear copiando el contenido de NuevoContacto, pues la implementación es casi idéntica. Para mantener el código organizado, lo haré en nuevos ficheros:

// fichero client/contactos/editar_contacto.html

<template name="EditarContacto">
  {{#ionModal customTemplate=true}}
    {{#autoForm collection="Contactos" id="editar-contacto" type="update" doc=contacto }}
      <div class="bar bar-header bar-stable bar-positive">
        <button data-dismiss="modal" type="button" class="button button-clear">Cancelar</button>
        <h2 class="title"> Editar contacto </h2>
        <button type="submit" class="button button-clear">Aceptar</button>
      </div>
      <div class="content has-header overflow-scroll">
        {{> afQuickFields }}
      </div>
    {{/autoForm}}
  {{/ionModal}}
</template>

Observa que cambié el id del formulario y el atributo type. Además agregué el atributo doc que tiene el Contacto a editar (brindado por un helper de este template llamado contacto).

La lógica JavaScript a aplicar para este template consta de tal helper y de los hooks para las funciones de éxito y fracaso:

Template.EditarContacto.helpers({
  contacto: function () {
    var template = Template.instance();
    return Contactos.findOne({ _id: template.data.id });
  }
});

AutoForm.hooks({
  'editar-contacto': {
    onSuccess: function (operation, result, template) {
      IonModal.close();
    },
    onError: function(operation, error, template) {
      alert(error);
    }
  }
});

Observa cómo obtengo el id del Contacto a editar desde el contexto de datos de la plantilla, accesible a través de Template.instance().data.id.

Comprueba que funciona

Con la implementación anterior dirígete a http://localhost:3000 y prueba ambos botones de adicionar y editar contacto. Trata de dejar algun campo vacío y observa la magia de validación automática.

Conclusiones

El paquete Autoform es imprescindible para agilizar el desarrollo en la mayoría de proyectos creados con Meteor. Para ver todas las posibilidades que tienes a tu alcance, te aconsejo leas la documentación de SimpleSchema, Collection2 y Autoform, pues este trío es más útil cuando se combinan sus potencialidades y no cuando se usan de manera aislada.

Por ejemplo, si no hubiese utilizado el paquete Collection2, tendría que haber asociado de forma manual el esquema creado a los formularios:

{{> AutoForm schema=ContactosSchema type="insert" id="insertar-contacto" }}

Con esta entrega termino la mayoría de los conceptos asociados al desarrollo de aplicaciones Meteor del lado del cliente.

En próximas entradas te enseñaré a Internacionalizar tu aplicación Meteor, así como conectarla al servidor y enviar notificaciones por correo.

¡El límite es el infinito!

  • Jesus

    Hola genial ! gracias por tu blog, cuando crees que podras publicar lo de Internacionalizar tu aplicación Meteor