<sect1 id="zend.form.elements">
    <title>Creando elementos de formulario usando Zend_Form_Element</title>

    <para>
        Un formulario esta compuesto de elementos, que normalmente corresponden 
        al  elemento HTML input. <code>Zend_Form_Element</code> encapsula
        elementos de formulario individualmente, con las siguientes áreas de 
        responsabilidad:
    </para>

    <itemizedlist>
        <listitem>
            <para>
                validación (¿los datos enviados son válidos?)
            </para>

            <itemizedlist>
                <listitem><para>captura de códigos y mensajes de error</para></listitem>
            </itemizedlist>
        </listitem>

        <listitem><para>
            filtrado (¿cómo es escapado y normalizado el elemento para su 
            validación y/o salida?
        </para></listitem>

        <listitem><para>
            generación (¿cómo es mostrado el elemento?)
        </para></listitem>

        <listitem><para>
            metadatos y atributos (¿qué información amplía la definición del
            elemento?)
        </para></listitem>
    </itemizedlist>

    <para>
        La clase base, <code>Zend_Form_Element</code>, funciona por defecto para
        varios casos, pero es mejor extender la clase para elementos con fines 
        especiales de uso común. Adicionalmente, Zend Framework contiene un 
        número de elementos XHTML estándar; puede leer de ellos <link linkend="zend.form.standarElements">en el capítulo Elementos
        Estándares</link>
    </para>

    <sect2 id="zend.form.elements.loaders">
        <title>Cargadores de Plugin</title>

        <para>
            <code>Zend_Form_Element</code> hace uso de <link linkend="zend.loader.pluginloader">Zend_Loader_PluginLoader</link>
            para permitir a los desarrolladores especificar ubicaciones de
            validadores, filtros y decoradores alternos. Cada uno tiene su 
            propio cargador de plugin asociado a él y métodos de acceso 
            generales usados para su recuperación y modificación.
        </para>

        <para>
            Los siguientes tipos de cargadores son usados con los varios métodos
            del cargador de plugin: 'validate', 'filter', y 'decorator'. Los
            nombres son sensibles a mayúsculas y minúsculas.
        </para>

        <para>
            Los métodos usados para interactuar con los cargadores de plugin son 
            los siguientes:
        </para>

        <itemizedlist>
            <listitem><para>
                <code>setPluginLoader($loader, $type)</code>:
                <code>$loader</code> es el propio objeto cargador, mientras
                <code>$type</code> es uno de los tipos arriba mencionados. Esto
                establece el cargador de plugin para el tipo dado en el objeto
                cargador recién especificado.
            </para></listitem>

            <listitem><para>
                <code>getPluginLoader($type)</code>: obtiene el cargador de
                plugin asociado con <code>$type</code>.
            </para></listitem>

            <listitem><para>
                <code>addPrefixPath($prefix, $path, $type = null)</code>: agrega
                una asociación prefijo/ruta para el cargador especificado por
                <code>$type</code>. Si <code>$type</code> es null, se intentará
                agregar la ruta a todos los cargadores, añadiendo el prefijo a
                cada "_Validate", "_Filter" y "_Decorator"; y agregandole
                "Validate/", "Filter/" y "Decorator/" a la ruta. Si tiene todas 
                sus clases extras para elementos de formulario dentro de
                una jerarquía común, este método es conveniente para establecer
                el prefijo para todas ellas.
            </para></listitem>

            <listitem><para>
                <code>addPrefixPaths(array $spec)</code>: le permite añadir
                varias rutas de una sola vez a uno o más cargadores de plugin.
                Se espera cada elemento de la matriz sea un array con claves
                'path', 'prefix', y 'type'.
            </para></listitem>
        </itemizedlist>

        <para>
            Validadores, filtros y decoradores personalizados son una manera
            simple de compartir funcionalidad entre formularios y encapsular
            funcionalidad personalizada.
        </para>

        <example id="zend.form.elements.loaders.customLabel">
            <title>Etiqueta personalizada</title>

            <para>
                Un uso común de los plugins es proveer reemplazos para las
                clases estándares. Por ejemplo, si desea proveer una implementación diferente
                 del decorador 'Label' -- por ejemplo, para
                añadir siempre dos puntos -- puede crear su  propio decorador 
                'Label' con su propio prefijo de clase, y entonces añadirlo a su 
                prefijo de ruta.
            </para>

            <para>
                Comencemos con un decorador de etiqueta personalizado. Le 
                daremos el prefijo "My_Decorator", y la clase estará en el 
                archivo "My/Decorator/Label.php".
            </para>

            <programlisting role="php"><![CDATA[
class My_Decorator_Label extends Zend_Form_Decorator_Abstract
{
    protected $_placement = 'PREPEND';

    public function render($content)
    {
        if (null === ($element = $this->getElement())) {
            return $content;
        }
        if (!method_exists($element, 'getLabel')) {
            return $content;
        }

        $label = $element->getLabel() . ':';

        if (null === ($view = $element->getView())) {
            return $this->renderLabel($content, $label);
        }

        $label = $view->formLabel($element->getName(), $label);

        return $this->renderLabel($content, $label);
    }

    public function renderLabel($content, $label)
    {
        $placement = $this->getPlacement();
        $separator = $this->getSeparator();

        switch ($placement) {
            case 'APPEND':
                return $content . $separator . $label;
            case 'PREPEND':
            default:
                return $label . $separator . $content;
        }
    }
}
]]>
            </programlisting>

            <para>
                Ahora diremos al elemento que use esta ruta cuando busque por
                decoradores:
            </para>

            <programlisting role="php"><![CDATA[
$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');
]]>
            </programlisting>

            <para>
                Alternativamente, podemos hacerlo en el formulario para asegurar
                que todos los decoradores usen esta ruta:
            </para>

            <programlisting role="php"><![CDATA[
$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');
]]>
            </programlisting>

            <para>
                Con esta ruta añadida, cuando agregue un decorador, la ruta
                'My/Decorator' será consultada primero en búsqueda de la 
                existencia del decorador en este lugar. Como resultado, 
                'My_Decorator_Label' ahora será utilizado cuando el decorador
                'Label' sea requerido.
            </para>
        </example>
    </sect2>

    <sect2 id="zend.form.elements.filters">
        <title>Filters</title>

        <para>
            A menudo es útil y/o necesario realizar alguna normalización en la
            entrada antes de la validación – por ejemplo, puede querer eliminar
            todo el HTML, pero realizar las validaciones sobre lo restante para
            asegurarse que el envío es válido. O puede eliminar los espacios en
            blanco al inicio o fin de la entrada para asegurarse de que un validador
            StringLenth (longitud de la cadena) no regrese un positivo falso. Estas
            operaciones pueden realizarse usando <code>Zend_Filter</code>, y
            <code>Zend_Form_Element</code> que soportan cadenas de filtros,
            permitiéndole especificar múltiples filtros secuenciales a utilizar.
            El filtrado sucede tanto en la validación como cuando recupera el
            valor del elemento vía <code>getValue()</code>:
        </para>

        <programlisting role="php"><![CDATA[
$filtered = $element->getValue();

]]>
        </programlisting>

        <para>
            Los filtros pueden ser agregados a la pila de dos maneras:
        </para>

        <itemizedlist>
            <listitem><para>
                pasándolo en una instancia de filtro específica
            </para></listitem>

            <listitem><para>
                proveyendo un nombre de filtro – el correspondiente nombre 
                corto o completo de la clase
            </para></listitem>
        </itemizedlist>

        <para>
            Veamos algunos ejemplos:
        </para>

        <programlisting role="php"><![CDATA[
// Instancia específica del filtro
$element->addFilter(new Zend_Filter_Alnum());

// El correspondiente nombre completo de la clase:
$element->addFilter('Zend_Filter_Alnum');

// Nombre corto del filtro:
$element->addFilter('Alnum');
$element->addFilter('alnum');
]]>
        </programlisting>

        <para>
            Los nombres cortos son típicamente el nombre del filtro sin el
            prefijo. En el caso predeterminado, esto se refiere a sin el prefijo
            'Zend_Filter_'. Además, la primera letra no necesita estar en 
            mayúscula.
        </para>

        <note>
            <title>Usando clases de filtros personalizados</title>

            <para>
                Si tiene su propio conjunto de clases de filtro, puede 
                informarle de ellas a <code>Zend_Form_Element</code> usando 
                <code>addPrefixPath()</code>. Por ejemplo, si tiene filtros
                con el prefijo 'My_Filter', puede indicárselo a
                <code>Zend_Form_Element</code> de la siguiente manera:
            </para>

            <programlisting role="php"><![CDATA[
$element->addPrefixPath('My_Filter', 'My/Filter/', 'filter');
]]>
            </programlisting>

            <para>
                (Recuerde que el tercer argumento indica el cargador de plugin
                sobre el cual ha de ejecutarse la acción.)
            </para>
        </note>

        <para>
            Si en algún momento necesita un valor no filtrado, use el método
            <code>getUnfilteredValue()</code>:
        </para>

        <programlisting role="php"><![CDATA[
$unfiltered = $element->getUnfilteredValue();
]]>
        </programlisting>

        <para>
            Para mayor información sobre filtros, vea la <link linkend="zend.filter.introduction">documentación de 
                Zend_Filter</link>.
        </para>

        <para>
            Métodos asociados con filtros incluyen:
        </para>

        <itemizedlist>
            <listitem><para>
                <code>addFilter($nameOfFilter, array $options = null)</code>
            </para></listitem>

            <listitem><para>
                <code>addFilters(array $filters)</code>
            </para></listitem>

            <listitem><para>
                <code>setFilters(array $filters)</code> (sobreescribe todos los
                filtros)
            </para></listitem>

            <listitem><para>
                <code>getFilter($name)</code> (recupera un objeto filtro por su
                nombre)
            </para></listitem>

            <listitem><para>
                <code>getFilters()</code> (recupera todos los filtros)
            </para></listitem>

            <listitem><para>
                <code>removeFilter($name)</code> (elimina un filtro por su
                nombre)
            </para></listitem>

            <listitem><para>
                <code>clearFilters()</code> (elimina todos los filtros)
            </para></listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.form.elements.validators">
        <title>Validadores</title>

        <para>
            Si sigue el mantra de seguridad "filtrar la entrada, escapar la
            salida" querrá validar ("filtrar la entrada") los datos de los
            formularios. En <code>Zend_Form</code> cada elemento contiene su
            propia cadena de validadores, consistente en validadores
            <code>Zend_Validate_*</code>.
        </para>

        <para>
            Los validadores pueden ser agregados de dos maneras:
        </para>

        <itemizedlist>
            <listitem><para>
                pasándolo en una instancia de validador específica
            </para></listitem>

            <listitem><para>
                proveyendo un nombre de validador – el correspondiente nombre 
                corto o completo de clase
            </para></listitem>
        </itemizedlist>

        <para>
            Veamos algunos ejemplos:
        </para>

        <programlisting role="php"><![CDATA[
// Instancia específica del validador:
$element->addValidator(new Zend_Validate_Alnum());

// El correspondiente nombre completo de la clase:
$element->addValidator('Zend_Validate_Alnum');

// Nombre corto del validador:
$element->addValidator('Alnum');
$element->addValidator('alnum');
]]>
        </programlisting>

        <para>
            Los nombres cortos son típicamente el nombre del validador sin el
            prefijo. En el caso predeterminado, esto se refiere a sin el prefijo
            'Zend_Validate_'. Además, la primera letra no necesita estar en
            mayúscula.
        </para>

        <note>
            <title>Usando clases de validación personalizadas</title>

            <para>
                Si tiene su propio conjunto de clases de validación, puede 
                informarle de ellas a <code>Zend_Form_Element</code> usando 
                <code>addPrefixPath()</code>. Por ejemplo, si tiene validadores
                con el prefijo 'My_Validator', puede indicárselo a
                <code>Zend_Form_Element</code> de la siguiente manera:
            </para>

            <programlisting role="php"><![CDATA[
$element->addPrefixPath('My_Validator', 'My/Validator/', 'validate');
]]>
            </programlisting>

            <para>
                (Recuerde que el tercer argumento indica el cargador de plugin
                sobre el cual ha de ejecutarse la acción.)
            </para>
        </note>

        <para>
            Si el fallo de un validador debe evitar validaciones posteriores,
            pase el boleano <code>true</code> como segundo parámetro:
        </para>

        <programlisting role="php"><![CDATA[
$element->addValidator('alnum', true);
]]>
        </programlisting>

        <para>
            Si está usando la cadena nombre para añadir el validador, y la clase 
            del validador acepta argumentos para su constructor, puede pasarlos
            a el tercer parámetro de <code>addValidator()</code> como un 
            array:
        </para>

        <programlisting role="php"><![CDATA[
$element->addValidator('StringLength', false, array(6, 20));
]]>
        </programlisting>

        <para>
            Los argumentos pasados de esta manera deben estar en el orden en el
            cual son definidos en el constructor. El ejemplo de arriba 
            instanciará la clase <code>Zend_Validate_StringLenth</code> con los
            parámetros <code>$min</code> y <code>$max</code>:
        </para>

        <programlisting role="php"><![CDATA[
$validator = new Zend_Validate_StringLength(6, 20);
]]>
        </programlisting>

        <note>
            <title>Estipulando mensajes de error de validación personalizados</title>

            <para>
                Algunos desarrolladores querrán estipular mensajes de error
                personalizados para un validador. El argumento 
                <code>$options</code> de 
                <code>Zend_Form_Element::addValidator()</code> le permite 
                hacerlo proporcionando la clave 'messages' y estableciendolos en 
                un array de pares clave/valor para especificar las plantillas 
                de mensaje. Necesitará conocer los códigos de error de los 
                diferentes tipos de error de un validador en particular.
            </para>

            <para>
                Una opción mejor es usar <code>Zend_Translate_Adapter</code>
                con su formulario. Los códigos de error son automáticamente 
                pasados al adaptador por el decorador Errors por defecto; puede 
                especificar su propias cadenas de mensaje de error mediante la 
                creación de traducciones para los varios códigos de error de 
                sus validadores.
            </para>
        </note>

        <para>
            Puede también establecer varios validadores a la vez, usando
            <code>addValidators()</code>. Su uso básico es pasar una matriz de
            arrays, donde cada array contenga de 1 a 3 valores, 
            correspondientes al constructor de <code>addValidator()</code>:
        </para>

        <programlisting role="php"><![CDATA[
$element->addValidators(array(
    array('NotEmpty', true),
    array('alnum'),
    array('stringLength', false, array(6, 20)),
));
]]>
        </programlisting>

        <para>
            Si quiere ser más detallado o explícito, puede utilizar las claves 
            'validator', 'breakChainOnFailure', y 'options' en el array:
        </para>

        <programlisting role="php"><![CDATA[
$element->addValidators(array(
    array(
        'validator'           => 'NotEmpty',
        'breakChainOnFailure' => true),
    array('validator' => 'alnum'),
    array(
        'validator' => 'stringLength',
        'options'   => array(6, 20)),
));
]]>
        </programlisting>

        <para>
            Este uso es bueno para ilustrar cómo puede configurar validadores
            en un archivo de configuración:
        </para>

        <programlisting role="ini"><![CDATA[
element.validators.notempty.validator = "NotEmpty"
element.validators.notempty.breakChainOnFailure = true
element.validators.alnum.validator = "Alnum"
element.validators.strlen.validator = "StringLength"
element.validators.strlen.options.min = 6
element.validators.strlen.options.max = 20
]]>
</programlisting>

        <para>
            Note que cada elemento tiene una clave, la necesite o no; esta es 
            una limitación del uso de archivos de configuración -- pero también 
            ayuda a hacer más explicito el para qué son usados los argumentos. 
            Sólo recuerde que cualesquiera opciones del validador deben ser 
            especificadas en orden.
        </para>

        <para>
            Para validar un elemento, pase el valor a
            <code>isValid()</code>:
        </para>

        <programlisting role="php"><![CDATA[
if ($element->isValid($value)) {
    // válido
} else {
    // no válido
}
]]>
        </programlisting>

        <note>
            <title>Validación operando en valores filtrados</title>

            <para>
                <code>Zend_Form_Element::isValid()</code> siempre filtra los 
                valores antes de la validación a través de la cadena de filtros.
                Vea <link linkend="zend.form.elements.filters">la sección de 
                filtros</link> para más información.
            </para>
        </note>

        <note>
            <title>Contexto de validación</title>

            <para>
                <code>Zend_Form_Element::isValid()</code> soporta un argumento
                adicional, <code>$context</code>.
                <code>Zend_Form::isValid()</code> pasa todo el conjunto de datos 
                procesados a <code>$context</code> cuando valida un formulario, 
                y <code>Zend_Form_Element::isValid()</code>, a su vez, lo pasa a 
                cada validador. Esto significa que puede escribir validadores 
                que son conscientes de los datos pasados a otros elementos del 
                formulario. Como ejemplo, considere un formulario de registro
                estándar que tiene campos para la contraseña y la confirmación 
                de la contraseña; una validación sería que los dos campos 
                coincidan. Este validador puede tener un aspecto como el 
                siguiente:
            </para>

            <programlisting role="php"><![CDATA[
class My_Validate_PasswordConfirmation extends Zend_Validate_Abstract
{
    const NOT_MATCH = 'notMatch';

    protected $_messageTemplates = array(
        self::NOT_MATCH => 'Password confirmation does not match'
    );

    public function isValid($value, $context = null)
    {
        $value = (string) $value;
        $this->_setValue($value);

        if (is_array($context)) {
            if (isset($context['password_confirm'])
                && ($value == $context['password_confirm']))
            {
                return true;
            }
        } elseif (is_string($context) && ($value == $context)) {
            return true;
        }

        $this->_error(self::NOT_MATCH);
        return false;
    }
}
]]>
            </programlisting>
        </note>

        <para>
            Los validadores son procesados en orden. Cada validador es 
            procesado, a menos que un validador creado con un valor true para
            <code>breakChainOnFailure</code> falle su validación. Asegúrese de 
            especificar sus validadores en un orden razonable.
        </para>

        <para>
            Después de una validación fallida, puede recuperar los códigos y 
            mensajes de error de la cadena del validador:
        </para>

        <programlisting role="php"><![CDATA[
$errors   = $element->getErrors();
$messages = $element->getMessages();
]]>
        </programlisting>

        <para>
            (Nota: los mensajes de error retornados son un array asociativo de
            pares código / mensaje de error.) 
        </para>

        <para>
            En adición a los validadores, puede especificar que un elemento es
            necesario, usando <code>setRequired(true)</code>. Por defecto, esta
            bandera es false, lo que significa que pasará su cadena de  
            validadores si ningún valor es pasado a <code>isValid()</code>. 
            Puede modificar este comportamiento en un número de maneras:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    Por defecto, cuando un elemento es requerido, una bandera,
                    'allowEmpty', también es true. Esto quiere decir que si un 
                    valor empty es evaluado pasándolo a <code>isValid()</code>, 
                    los validadores serán saltados. Puede intercalar esta
                    bandera usando el método de acceso 
                    <code>setAllowEmpty($flag)</code>; cuando la bandera es 
                    false, si un valor es pasado, los validadores seguirán 
                    ejecutándose.
                </para>
            </listitem>

            <listitem>
                <para>
                    Por defecto, si un elemento es requerido, pero no contiene
                    un validador 'NotEmpty', <code>isValid()</code> añadirá uno
                    en la cima de la pila, con la bandera 
                    <code>breakChainOnFailure</code> establecido. Esto hace que 
                    la bandera requerida tenga un significado semántico: si 
                    ningún valor es pasado, inmediatamente invalidamos el envío 
                    y se le notifica al usuario, e impedimos que otros 
                    validadores se ejecuten en lo que ya sabemos son datos 
                    inválidos.
                </para>

                <para>
                    Si no quiere este comportamiento, puede desactivarlo pasando
                    un valor false a 
                    <code>setAutoInsertNotEmptyValidator($flag)</code>; esto
                    prevendrá a <code>isValid()</code> de colocar un validador 
                    'NotEmpty' en la cadena de validaciones.
                </para>
            </listitem>
        </itemizedlist>

        <para>
            Para mayor información sobre validadores, vea la <link linkend="zend.validate.introduction">documentación de 
                Zend_Validate</link>.
        </para>

        <note>
            <title>Usando Zend_Form_Elements como validador de propósito general</title>

            <para>
                <code>Zend_Form_Element</code> implementa
                <code>Zend_Validate_Interface</code>, significando un elemento
                puede también usarse como un validador en otro, cadenas de 
                validación no relacionadas al formulario.
            </para>
        </note>

        <para>
            Métodos asociados con validación incluyen:
        </para>

        <itemizedlist>
            <listitem><para>
                    <code>setRequired($flag)</code> y
                    <code>isRequired()</code> permiten establecer y recuperar el 
                    estado de la bandera 'required'. Cuando se le asigna un 
                    booleano <code>true</code>, esta bandera requiere que el
                    elemento esté presente en la información procesada por 
                    <code>Zend_Form</code>.
            </para></listitem>

            <listitem><para>
                    <code>setAllowEmpty($flag)</code> y
                    <code>getAllowEmpty()</code> permiten modificar el 
                    comportamiento de elementos opcionales (p.e., elementos 
                    donde la bandera required es false). Cuando la bandera  
                    'allow empty' es true, valores vacíos no pasarán la cadena
                    de validadores.
            </para></listitem>

            <listitem><para>
                    <code>setAutoInsertNotEmptyValidator($flag)</code> permite
                    especificar si realmente un validador 'NotEmpty' será 
                    añadido el inicio de la cadena de validaciones cuando un 
                    elemento es requerido. Por defecto, esta bandera es true.
            </para></listitem>

            <listitem><para>
                <code>addValidator($nameOrValidator, $breakChainOnFailure = false, array $options = null)</code>
            </para></listitem>

            <listitem><para>
                <code>addValidators(array $validators)</code>
            </para></listitem>

            <listitem><para>
                <code>setValidators(array $validators)</code> (sobreescribe todos los validadores)
            </para></listitem>

            <listitem><para>
                <code>getValidator($name)</code> (recupera un objeto validador por nombre)
            </para></listitem>

            <listitem><para>
                <code>getValidators()</code> (recupera todos los validadores)
            </para></listitem>

            <listitem><para>
                <code>removeValidator($name)</code> (elimina un validador por nombre)
            </para></listitem>

            <listitem><para>
                <code>clearValidators()</code> (elimina todos los validadores)
            </para></listitem>
        </itemizedlist>

        <sect3 id="zend.form.elements.validators.errors">
            <title>Errores de mensaje personalizados</title>

            <para>
                Alguna veces, querrá especificar uno o más mensajes de error para
                usarlos en lugar de los mensajes de error generados por los 
                validadores adjuntos a los elementos. Adicionalmente, algunas
                veces usted mismo querrá marcar al elemento como inválido. A 
                partir de 1.6.0, esta funcionalidad es posible vía los 
                siguientes métodos. 
            </para>

            <itemizedlist>
                <listitem><para>
                    <code>addErrorMessage($message)</code>: añade un mensaje de 
                    error para mostrarlos en forma de errores de validación. Puede 
                    llamarlo más de una vez, y los nuevos mensajes nuevos son 
                    añadidos a la pila.
                </para></listitem>

                <listitem><para>
                    <code>addErrorMessages(array $messages)</code>: añade 
                    múltiples mensajes de error para mostrarlos en forma de errores de
                    validación.
                </para></listitem>

                <listitem><para>
                    <code>setErrorMessages(array $messages)</code>: añade 
                    múltiples mensajes de error para mostrarlos en forma de errores de
                    validación, sobreescribiendo todos los mensajes de error 
                    previamente establecidos. 
                </para></listitem>

                <listitem><para>
                    <code>getErrorMessages()</code>: recupera la lista de 
                    mensajes de error personalizados que fueron definidos.
                </para></listitem>

                <listitem><para>
                    <code>clearErrorMessages()</code>: remueve todos los 
                    mensajes de error personalizados que hayan sido definidos.
                </para></listitem>

                <listitem><para>
                    <code>markAsError()</code>: marca al elemento como que falló 
                    la validación.
                </para></listitem>

                <listitem><para>
                    <code>hasErrors()</code>: determina si el elemento ha 
                    fallado la validación o ha sido marcado como inválido.
                </para></listitem>

                <listitem><para>
                    <code>addError($message)</code>: añade un mensaje a la pila
                    de mensaje de error personalizados y marca al elemento como 
                    inválido.
                </para></listitem>

                <listitem><para>
                    <code>addErrors(array $messages)</code>: añade varios 
                    mensajes a la pila de mensajes de error personalizados y 
                    marca al elemento como inválido.
                </para></listitem>

                <listitem><para>
                    <code>setErrors(array $messages)</code>: sobreescribe el 
                    mensaje de error personalizado en la pila con los mensajes
                    previstos y marca al elemento como inválido.
                </para></listitem>
            </itemizedlist>

            <para>
                Todos los errores establecidos de este modo pueden ser 
                traducidos. Adicionalmente, puede insertar el marcador "%value%" 
                para representar el valor del elemento; este valor actual del 
                elemento será sustituido cuando el mensaje de error sea 
                recuperado.
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.form.elements.decorators">
        <title>Decoradores</title>

        <para>
            Una dolencia particular para muchos desarrolladores web es la creación
            del XHTML para formularios por ellos mismos. Para cada elemento, el
            desarrollador necesita crear la marcación para el elemento mismo,
            comúnmente una etiqueta (label), y, si son amables con sus usuarios,
            la marcación para mostrar mensajes de errores de validación. Cuanto
            más elementos en una página, menos trivial se convierte esta tarea.
        </para>

        <para>
            <code>Zend_Form_Element</code> intenta resolver este problema mediante
            el uso de "decoradores". Los decoradores son clases simples que tienen
            métodos de acceso al elemento y métodos para generar el contenido. Para
            obtener mayor información sobre cómo trabajan los decoradores, consulte
            por favor  la sección sobre 
            <link linkend="zend.form.decorators">Zend_Form_Decorator</link>.
        </para>

        <para>
            Los decoradores usados por defecto por
            <code>Zend_Form_Element</code> son:
        </para>

        <itemizedlist>
            <listitem><para>
                <emphasis>ViewHelper</emphasis>: especifica un view helper que
                usar para general el elemento. El atributo 'helper' del elemento
                puede usarse para especificar qué auxiliar vista usar. Por
                defecto, <code>Zend_Form_Element</code> especifica el auxiliar
                vista 'formText', pero cada subclase especifica diferentes 
                auxiliares.
            </para></listitem>

            <listitem><para>
                <emphasis>Errors</emphasis>: añade mensajes de error al elemento
                usando <code>Zend_View_Helper_FormErrors</code>. Si no está
                presente, no se añade nada.
            </para></listitem>

            <listitem><para>
                <emphasis>Description</emphasis>: añade la descripción del
                elemento. Si no está presente, no se añade nada. Por defecto, la
                descripción es generada dentro de una etiqueta &lt;p&gt; con un
                class 'description'.
            </para></listitem>

            <listitem><para>
                <emphasis>HtmlTag</emphasis>: envuelve el elemento y los errores
                en una etiqueta HTML &lt;dd&gt;.
            </para></listitem>

            <listitem><para>
                <emphasis>Label</emphasis>: añade al comienzo una etiqueta al
                elemento usando <code>Zend_View_Helper_FormLabel</code>, y
                envolviéndola en una etiqueta &lt;dt&gt;. Si ninguna etiqueta es
                provista, solo la etiqueta de la definición es generada.
            </para></listitem>
        </itemizedlist>

        <note>
            <title>Decoradores por defecto no necesitan ser cargados</title>

            <para>
                Por defecto, los decoradores por defecto son cargados durante la
                inicialización del objeto. Puede deshabilitar esto pasando la
                opción 'disableLoadDefaultDecorators' al constructor:
            </para>

            <programlisting role="php"><![CDATA[
$element = new Zend_Form_Element('foo',
                                 array('disableLoadDefaultDecorators' =>
                                      true)
                                );
]]>
            </programlisting>

            <para>
                Esta opción puede ser combinada junto con cualquier otra opción que
                pase, ya sea como un array de opciones o en un objeto
                <code>Zend_Config</code>.
            </para>
        </note>

        <para>
            Ya que el orden en el cual los decoradores son registrados importa
            -- el primer decorador registrado es ejecutado primero -- necesitará
            estar seguro de registrar sus decoradores en el orden apropiado, o
            asegurarse de que estableció las opciones de colocación en el modo apropiado. Por
            dar un ejemplo, aquí esta el código que registran los decoradores
            por defecto:
        </para>

        <programlisting role="php"><![CDATA[
$this->addDecorators(array(
    array('ViewHelper'),
    array('Errors'),
    array('Description', array('tag' => 'p', 'class' => 'description')),
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));
]]>
        </programlisting>

        <para>
            El contenido inicial es creado por el decorador 'ViewHelper', que
            crea el propio elemento. En seguida, el decorador 'Errors' consulta
            los mensajes de error del elemento, y, si hay alguno presente, los
            pasa al auxiliar vista 'FormErrors' para mostrarlos. Si una
            descripción está presente, el decorador 'Description' añadirá
            un párrafo con class 'description' conteniendo el texto descriptivo
            para el contenido agregado. El siguiente decorador, 'HtmlTag',
            envuelve al elemento, los errores, y la descripción en una etiqueta 
            HTML &lt;dd&gt;. Finalmente, el último decorador, 'label', recupera
            la etiqueta del elemento y la pasa al auxiliar vista 'FormLabel',
            envolviéndolo en una etiqueta &lt;dt&gt;; por default el valor es 
            añadido al inicio del contenido. El resultado de la salida
            básicamente se ve así:
        </para>

        <programlisting role="html"><![CDATA[
<dt><label for="foo" class="optional">Foo</label></dt>
<dd>
    <input type="text" name="foo" id="foo" value="123" />
    <ul class="errors">
        <li>"123" is not an alphanumeric value</li>
    </ul>
    <p class="description">
        This is some descriptive text regarding the element.
    </p>
</dd>
]]>
</programlisting>

        <para>
            Para más información sobre decoradores, lea la <link linkend="zend.form.decorators"> sección de Zend_Form_Decorator</link>.
        </para>

        <note>
            <title>Usando múltiples decoradores al mismo tiempo</title>

            <para>
                Internamente, <code>Zend_Form_Element</code> utiliza una clase
                decorador como mecanismo de búsqueda para la recuperación de
                decoradores. Como resultado, no puede registrar múltiples 
                decoradores del mismo tipo; decoradores subsecuentes 
                simplemente sobreescribirán aquellos que ya existían.
            </para>

            <para>
                Para evitar esto, puede usar <emphasis>alias</emphasis>. En
                lugar de pasar un decorador o nombre de decorador como primer
                argumento a <code>addDecorator()</code>, pase una matriz con un
                solo elemento, con el alias apuntando al nombre o objeto
                decorador:
            </para>

            <programlisting role="php"><![CDATA[
// Alias a 'FooBar':
$element->addDecorator(array('FooBar' => 'HtmlTag'),
                       array('tag' => 'div'));

// Y recuperandolo posteriormente:
$decorator = $element->getDecorator('FooBar');
]]>
            </programlisting>

            <para>
                En los métodos <code>addDecorators()</code> y
                <code>setDecorators()</code>, necesitará pasar la opción
                'decorator' en la matriz representando el decorador:
            </para>

            <programlisting role="php"><![CDATA[
// Y dos decoradores 'HtmlTag', 'FooBar' como alias:
$element->addDecorators(
    array('HtmlTag', array('tag' => 'div')),
    array(
        'decorator' => array('FooBar' => 'HtmlTag'),
        'options' => array('tag' => 'dd')
    ),
);

// Y recuperándolos posteriormente:
$htmlTag = $element->getDecorator('HtmlTag');
$fooBar  = $element->getDecorator('FooBar');
]]>
            </programlisting>
        </note>

        <para>
            Métodos asociados con decoradores incluyen:
        </para>

        <itemizedlist>
            <listitem><para>
                <code>addDecorator($nameOrDecorator, array $options = null)</code>
            </para></listitem>

            <listitem><para>
                <code>addDecorators(array $decorators)</code>
            </para></listitem>

            <listitem><para>
                <code>setDecorators(array $decorators)</code> (sobreescribe
                todos los decoradores)
            </para></listitem>

            <listitem><para>
                <code>getDecorator($name)</code> (recupera un objeto decorador
                por su nombre)
            </para></listitem>

            <listitem><para>
                <code>getDecorators()</code> (recupera todos los decoradores)
            </para></listitem>

            <listitem><para>
                <code>removeDecorator($name)</code> (elimina un decorador por su
                nombre)
            </para></listitem>

            <listitem><para>
                <code>clearDecorators()</code> (elimina todos los decoradores)
            </para></listitem>
        </itemizedlist>

        <para>
            <code>Zend_Form_Element</code> también utiliza la sobrecarga para
            permitir generar decoradores específicos. <code>__call()</code>
            interceptará métodos que comiencen con el texto 'render' y utilizará
            el resto del nombre del método para buscar un decorador; si se
            encuentra, entonces será generado <emphasis>sólo ese</emphasis> 
            decorador. Cualquier argumento pasado al llamado del método será
            usado como contenido para pasar  al método <code>render()</code> del
            decorador. Como ejemplo:
        </para>

        <programlisting role="php"><![CDATA[
// Genera solo el decorador ViewHelper:
echo $element->renderViewHelper();

// Genera solo el decorador HtmlTag, pasándole contenido:
echo $element->renderHtmlTag("This is the html tag content");
]]></programlisting>

        <para>
            Si el decorador no existe, una excepción es lanzada.
        </para>
    </sect2>

    <sect2 id="zend.form.elements.metadata">
        <title>Metadatos y atributos</title>

        <para>
            <code>Zend_Form_Element</code> manipula una variedad de atributos y
            medatados del elemento. Atributos básicos incluyen:
        </para>

        <itemizedlist>
            <listitem><para>
                <emphasis>name</emphasis>: el nombre del elemento. Emplea los
                métodos de acceso <code>setName()</code> y <code>getName()</code>.
            </para></listitem>

            <listitem><para>
                <emphasis>label</emphasis>: la etiqueta del elemento. Emplea los
                métodos de acceso <code>setLabel()</code> y <code>getLabel()</code>.
            </para></listitem>

            <listitem><para>
                <emphasis>order</emphasis>: el índice en el cual los elementos
                deben ir mostrándose en el formulario. Emplea los métodos de
                acceso <code>setOrder()</code> y <code>getOrder()</code>.
            </para></listitem>

            <listitem><para>
                <emphasis>value</emphasis>: El valor del elemento actual. Emplea
                los métodos de acceso <code>setValue()</code> y 
                <code>getValue()</code>.
            </para></listitem>

            <listitem><para>
                <emphasis>description</emphasis>: una descripción del elemento;
                a menudo utilizada para proveer un tooltip o ayuda contextual
                con javascript describiendo el propósito del elemento. Emplea
                los métodos de acceso <code>setDescription()</code> y 
                <code>getDescription()</code>.
            </para></listitem>

            <listitem><para>
                <emphasis>required</emphasis>: bandera que indica si un elemento
                es requerido o no cuando se efectúa la validación del
                formulario. Emplea los métodos de acceso 
                <code>setRequired()</code> y <code>getRequired()</code>. Esta
                bandera es false por defecto.
            </para></listitem>

            <listitem><para>
                <emphasis>allowEmpty</emphasis>: bandera indicando si un
                elemento no-requerido (opcional) debe intentar validar o no
                valores vacíos. Cuando es true, y la bandera required es false,
                valores vacíos no pasarán la cadena de validación, y se supone
                verdadero. Emplea los métodos de acceso 
                <code>setAllowEmpty()</code> y <code>getAllowEmpty()</code>.
                Esta bandera es true por defecto.
            </para></listitem>

            <listitem><para>
                <emphasis>autoInsertNotEmptyValidator</emphasis>: bandera 
                indicando insertar o no un validador 'NotEmpty' cuando un
                elemento es requerido. Por defecto, esta bandera es true.
                Establezca la bandera con
                <code>setAutoInsertNotEmptyValidator($flag)</code> y determine
                el valor con <code>autoInsertNotEmptyValidator()</code>.
            </para></listitem>
        </itemizedlist>

        <para>
            Los elementos del formulario pueden requerir metainformación
            adicional. Para elementos XHTML del formuladio, por ejemplo, puede
            querer especificar atributos como el class o id. Para facilitar esto
            hay un conjunto de métodos de acceso:
        </para>

        <itemizedlist>
            <listitem><para>
                <emphasis>setAttrib($name, $value)</emphasis>: añade un atributo
            </para></listitem>

            <listitem><para>
                <emphasis>setAttribs(array $attribs)</emphasis>: como
                addAttribs(), pero sobreescribiendo
            </para></listitem>

            <listitem><para>
                <emphasis>getAttrib($name)</emphasis>: recupera el valor de solo
                un atributo
            </para></listitem>

            <listitem><para>
                <emphasis>getAttribs()</emphasis>: recupera todos los atributos
                como pares clave/valor
            </para></listitem>
        </itemizedlist>

        <para>
            La mayoría de las veces, como sea, puede simplemente acceder a ellos
            como propiedades de objeto, ya que <code>Zend_Form_Element</code>
            utiliza la sobrecarga para facilitar el acceso a ellos:
        </para>

        <programlisting role="php"><![CDATA[
// Equivalente a $element->setAttrib('class', 'text'):
$element->class = 'text;
]]>
        </programlisting>

        <para>
            Por defecto, todos los atributos son pasados al auxiliar vista usado 
            por el elemento durante la generación, y generados como atributos de
            la etiqueta del elemento.
        </para>
    </sect2>

    <sect2 id="zend.form.elements.standard">
        <title>Elementos Estándar</title>

        <para>
            <code>Zend_Form</code> contiene un buen número de elementos
            estándar; por favor lea el capítulo <link linkend="zend.form.standarElements">Elementos Estándar</link> para
            todos los detalles.
        </para>
    </sect2>

    <sect2 id="zend.form.elements.methods">
        <title>Métodos de Zend_Form_Element</title>

        <para>
            <code>Zend_Form_Element</code> tiene muchos, muchos métodos. Lo que
            sigue es un sumario de sus funciones, agrupados por tipo:
        </para>

        <itemizedlist>
            <listitem><para>Configuración:</para>
                <itemizedlist>
                    <listitem><para><code>setOptions(array $options)</code></para></listitem>
                    <listitem><para><code>setConfig(Zend_Config $config)</code></para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>I18n:</para>
                <itemizedlist>
                    <listitem><para><code>setTranslator(Zend_Translate_Adapter $translator = null)</code></para></listitem>
                    <listitem><para><code>getTranslator()</code></para></listitem>
                    <listitem><para><code>setDisableTranslator($flag)</code></para></listitem>
                    <listitem><para><code>translatorIsDisabled()</code></para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>Propiedades:</para>
                <itemizedlist>
                    <listitem><para><code>setName($name)</code></para></listitem>
                    <listitem><para><code>getName()</code></para></listitem>
                    <listitem><para><code>setValue($value)</code></para></listitem>
                    <listitem><para><code>getValue()</code></para></listitem>
                    <listitem><para><code>getUnfilteredValue()</code></para></listitem>
                    <listitem><para><code>setLabel($label)</code></para></listitem>
                    <listitem><para><code>getLabel()</code></para></listitem>
                    <listitem><para><code>setDescription($description)</code></para></listitem>
                    <listitem><para><code>getDescription()</code></para></listitem>
                    <listitem><para><code>setOrder($order)</code></para></listitem>
                    <listitem><para><code>getOrder()</code></para></listitem>
                    <listitem><para><code>setRequired($flag)</code></para></listitem>
                    <listitem><para><code>getRequired()</code></para></listitem>
                    <listitem><para><code>setAllowEmpty($flag)</code></para></listitem>
                    <listitem><para><code>getAllowEmpty()</code></para></listitem>
                    <listitem><para><code>setAutoInsertNotEmptyValidator($flag)</code></para></listitem>
                    <listitem><para><code>autoInsertNotEmptyValidator()</code></para></listitem>
                    <listitem><para><code>setIgnore($flag)</code></para></listitem>
                    <listitem><para><code>getIgnore()</code></para></listitem>
                    <listitem><para><code>getType()</code></para></listitem>
                    <listitem><para><code>setAttrib($name, $value)</code></para></listitem>
                    <listitem><para><code>setAttribs(array $attribs)</code></para></listitem>
                    <listitem><para><code>getAttrib($name)</code></para></listitem>
                    <listitem><para><code>getAttribs()</code></para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>Cargadores y rutas de plugin:</para>
                <itemizedlist>
                    <listitem><para><code>setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)</code></para></listitem>
                    <listitem><para><code>getPluginLoader($type)</code></para></listitem>
                    <listitem><para><code>addPrefixPath($prefix, $path, $type = null)</code></para></listitem>
                    <listitem><para><code>addPrefixPaths(array $spec)</code></para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>Validación:</para>
                <itemizedlist>
                    <listitem><para><code>addValidator($validator, $breakChainOnFailure = false, $options = array())</code></para></listitem>
                    <listitem><para><code>addValidators(array $validators)</code></para></listitem>
                    <listitem><para><code>setValidators(array $validators)</code></para></listitem>
                    <listitem><para><code>getValidator($name)</code></para></listitem>
                    <listitem><para><code>getValidators()</code></para></listitem>
                    <listitem><para><code>removeValidator($name)</code></para></listitem>
                    <listitem><para><code>clearValidators()</code></para></listitem>
                    <listitem><para><code>isValid($value, $context = null)</code></para></listitem>
                    <listitem><para><code>getErrors()</code></para></listitem>
                    <listitem><para><code>getMessages()</code></para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>Filtros:</para>
                <itemizedlist>
                    <listitem><para><code>addFilter($filter, $options = array())</code></para></listitem>
                    <listitem><para><code>addFilters(array $filters)</code></para></listitem>
                    <listitem><para><code>setFilters(array $filters)</code></para></listitem>
                    <listitem><para><code>getFilter($name)</code></para></listitem>
                    <listitem><para><code>getFilters()</code></para></listitem>
                    <listitem><para><code>removeFilter($name)</code></para></listitem>
                    <listitem><para><code>clearFilters()</code></para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>Generación:</para>
                <itemizedlist>
                    <listitem><para><code>setView(Zend_View_Interface $view = null)</code></para></listitem>
                    <listitem><para><code>getView()</code></para></listitem>
                    <listitem><para><code>addDecorator($decorator, $options = null)</code></para></listitem>
                    <listitem><para><code>addDecorators(array $decorators)</code></para></listitem>
                    <listitem><para><code>setDecorators(array $decorators)</code></para></listitem>
                    <listitem><para><code>getDecorator($name)</code></para></listitem>
                    <listitem><para><code>getDecorators()</code></para></listitem>
                    <listitem><para><code>removeDecorator($name)</code></para></listitem>
                    <listitem><para><code>clearDecorators()</code></para></listitem>
                    <listitem><para><code>render(Zend_View_Interface $view = null)</code></para></listitem>
                </itemizedlist>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.form.elements.config">
        <title>Configuración</title>

        <para>
            El constructor de <code>Zend_Form_Element</code> acepta tanto una
            matriz de opciones como un objeto <code>Zend_Config</code>
            conteniendo opciones, y esto puede configurarse usando
            <code>setOptions()</code> o <code>setConfig()</code>. Hablando de
            manera general, las claves son nombradas de la siguiente manera:
        </para>

        <itemizedlist>
            <listitem><para>
                Si 'set' + clave se refiere a un método de 
                <code>Zend_Form_Element</code>, entonces el valor provisto será
                pasado a el método.
            </para></listitem>

            <listitem><para>
                De otra manera, el valor será usado para establecer un atributo.
            </para></listitem>
        </itemizedlist>

        <para>
            Excepciones a la regla incluyen las siguientes:
        </para>

        <itemizedlist>
            <listitem><para>
                <code>prefixPath</code> será pasado a
                <code>addPrefixPaths()</code>
            </para></listitem>

            <listitem>
                <para>
                    Los siguientes setters no pueden establecerse de esta manera:
                </para>

                <itemizedlist>
                    <listitem><para>
                            <code>setAttrib</code> (aunque
                            <code>setAttribs</code> <emphasis>funcionará</emphasis>
                    </para></listitem>

                    <listitem><para><code>setConfig</code></para></listitem>

                    <listitem><para><code>setOptions</code></para></listitem>

                    <listitem><para><code>setPluginLoader</code></para></listitem>

                    <listitem><para><code>setTranslator</code></para></listitem>

                    <listitem><para><code>setView</code></para></listitem>
                </itemizedlist>
            </listitem>
        </itemizedlist>

        <para>
            Como ejemplo, aquí esta un archivo de configuración pasado para
            cada tipo de dato configurable:
        </para>

        <programlisting role="ini"><![CDATA[
[element]
name = "foo"
value = "foobar"
label = "Foo:"
order = 10
required = true
allowEmpty = false
autoInsertNotEmptyValidator = true
description = "Foo elements are for examples"
ignore = false
attribs.id = "foo"
attribs.class = "element"
; sets 'onclick' attribute
onclick = "autoComplete(this, '/form/autocomplete/element')"
prefixPaths.decorator.prefix = "My_Decorator"
prefixPaths.decorator.path = "My/Decorator/"
disableTranslator = 0
validators.required.validator = "NotEmpty"
validators.required.breakChainOnFailure = true
validators.alpha.validator = "alpha"
validators.regex.validator = "regex"
validators.regex.options.pattern = "/^[A-F].*/$"
filters.ucase.filter = "StringToUpper"
decorators.element.decorator = "ViewHelper"
decorators.element.options.helper = "FormText"
decorators.label.decorator = "Label"
]]>
</programlisting>
    </sect2>

    <sect2 id="zend.form.elements.custom">
        <title>Elementos personalizados</title>

        <para>
            Usted puede crear sus propios elementos personalizados simplemente
            extendiendo la clase <code>Zend_Form_Element</code>. Las razones
            comunes para hacer esto incluyen:
        </para>

        <itemizedlist>
            <listitem><para>
                Elementos que comparten validadores y/o filtros comunes 
            </para></listitem>

            <listitem><para>
                Elementos que tienen decoradores con funcionalidad personalizada
            </para></listitem>
        </itemizedlist>

        <para>
            Hay dos métodos típicamente usados para extender un elemento:
            <code>init()</code>, el cual puede usarse para añadir una lógica de
            inicialización personalizada a su elemento, y
            <code>loadDefaultDecorators()</code>, el cual puede usarse para
            establecer una lista de decoradores usados por su elemento de manera
            predeterminada.
        </para>

        <para>
            Como un ejemplo, digamos que todos los elementos de tipo texto en un
            formulario que está creando, necesitan ser filtrados con
            <code>StringTrim</code>, validados con una expresión regular, y que
            quiere usar un decorador personalizado que ha creado para
            mostrarlos, 'My_Decorator_TextItem'; adicionalmente, tiene un número
            de atributos estándars, incluyendo 'size', 'maxLength', y 'class'
            que quisiera especificar. Puede definir un elemento tal como sigue:
        </para>

        <programlisting role="php"><![CDATA[
class My_Element_Text extends Zend_Form_Element
{
    public function init()
    {
        $this->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator')
             ->addFilters('StringTrim')
             ->addValidator('Regex', false, array('/^[a-z0-9]{6,}$/i'))
             ->addDecorator('TextItem')
             ->setAttrib('size', 30)
             ->setAttrib('maxLength', 45)
             ->setAttrib('class', 'text');
    }
}
]]>
        </programlisting>

        <para>
            Entonces puede informar a su objeto formulario acerca del prefijo de
            ruta para elementos de ese tipo, y comenzar creando elementos:
        </para>

        <programlisting role="php"><![CDATA[
$form->addPrefixPath('My_Element', 'My/Element/', 'element')
     ->addElement('foo', 'text');
]]>
        </programlisting>

        <para>
            El elemento 'foo' será ahora del tipo <code>My_Element_Text</code>,
            y mostrará el comportamiento que ha especificado.
        </para>

        <para>
            Otro método que puede querer sobreescribir cuando extienda
            <code>Zend_Form_Element</code> es el método
            <code>loadDefaultDecorators()</code>. Este método carga
            condicionalmente un grupo de decoradores predefinidos para su
            elemento; puede querer sustituir su propio decorador en su clase
            extendida:
        </para>

        <programlisting role="php"><![CDATA[
class My_Element_Text extends Zend_Form_Element
{
    public function loadDefaultDecorators()
    {
        $this->addDecorator('ViewHelper')
             ->addDecorator('DisplayError')
             ->addDecorator('Label')
             ->addDecorator('HtmlTag',
                            array('tag' => 'div', 'class' => 'element'));
    }
}
]]>
        </programlisting>

        <para>
            Hay muchas maneras de personalizar elementos; asegúrese de leer la
            documentación de la API de <code>Zend_Form_Element</code> para
            conocer todos los métodos disponibles.
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 tw=80 ai et:
-->
