react-native-baum-form

Si su aplicación React Native usa múltiples formularios, con esta dependencia sólo necesitará ajustar estilos y declarar métodos.

Usage no npm install needed!

<script type="module">
  import reactNativeBaumForm from 'https://cdn.skypack.dev/react-native-baum-form';
</script>

README

React Native Baum Form (Beta V0.0.11)

Esta es una dependencia para React Native creada por la empresa costarricense BaumDigital.

"Si su aplicación React Native usa múltiples formularios, con esta dependencia sólo necesitará ajustar estilos y declarar métodos".

En resumen, esta dependencia únicamente necesita:

  • Una función que retorne un objeto con las estructuras de los formularios de su aplicación.
  • Una función que retorne un objeto con las reglas que debe seguir el formulario para validar sus datos.
  • Una función que retorne un objeto con los componentes que usará el formulario y que reciben la lógica de la dependencia.
  • Un componente que una las tres funciones anteriores a la dependencia.

Instalación

Esta es una dependencia 100% JavaScript y JSX por lo que no se necesita usar "link".

$ npm install react-native-baum-form --save

¿Cómo se usa?

Nota: Esta documentación se encuentra aún en proceso de ampliación, está incompleta.

En un mismo folder, necesita tener los siguientes archivos:

Archivo Descripción
rules.js Reglas tipo regex o métodos que validan los datos del formulario.
structure.js Estructuras (Tipos de formularios) que se usarán en la aplicación.
components.js Componentes que reciben la lógica del formulario y que son el aspecto del mismo.
index.js Componente que conecta la dependencia a las estructuras del formulario, las reglas que debe seguir y los componentes que se deben usar.

structure.js

Analice el siguiente ejemplo y preste atención a las notas:

export default ({ language }) => ({ //Por aquí se pueden recibir propiedades.
    LogIn: [
        {
            //Cada uno de estos objetos equivale a un componente, en este caso, un Input.
            show: true,
            type: 'Input',
            name: 'username',
            
            required: true,
            security: false,
            placeholder: language.username
        },
        {
            //Estas son propiedades que solicita la dependencia.
            show: true,
            type: 'Input',
            name: 'password',
            
            //Estas son propiedades "custom" de este proyecto, pueden haber las que se necesite, sólo se deben conectar al componente que se desee en components.js
            required: true,
            security: true,
            placeholder: language.password
        },
        {
            show: true,
            type: 'Forget',
            name: 'forget',
            placeholder: '¿Olvidó su contraseña?'
        }
    ],
    LogInConfirmation: [
        {
            show: true,
            type: 'Input',
            name: 'username',
            
            required: true,
            security: false,
            placeholder: language.username
        },
        [
            //Se pueden ordenar los componentes horizontalmente usando un array, sólo cuide sus estilos de components.js
            {
                show: true,
                type: 'Input',
                name: 'password',
                
                required: true,
                security: true,
                placeholder: language.password
            },
            {
                show: true,
                type: 'Input',
                name: 'confirmation',
                
                required: true,
                security: true,
                placeholder: 'Confirmación'
            }
        ]
    ],
    Recover: [
        {
            show: true,
            type: 'Input',
            name: 'username',
            
            required: true,
            security: false,
            placeholder: 'Correo o ID'
        }
    ]
});

Propiedades del objeto:

Propiedad Descripción
show (Boolean) Define si mostrar o no el componente que representa este objeto.
type Es el tipo de componente que representa el objeto, debe existir un componente con el mismo nombre en components.js
name Nombre de la propiedad que posé el valor del componente, por ejemplo, si name se llama "username", dentro del formulario, eso se representaría así => username: 'Lo que escriba el usuario'.
En este ejemplo, tenemos tres formularios, uno se llama "LogIn", el otro "LogInConfirmation" y el último "Recover", más adelante en index.js los usaremos.

rules.js

Analice el siguiente ejemplo y preste atención a las notas:

//Estos son rejex que evalúan números y correos.
const numeros = /^-?\d+$/;
const correos = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;

export default ({ language }) => ({ //Por aquí se pueden recibir propiedades.
    username: {
        regex: [],
        method: [
            {
                validation: v => ((v.length > 0) && ((numeros.test(v)) ? !correos.test(v) : correos.test(v))),
                message: language.usernameError
            }
        ],
        compare: false
    },
    password: {
        regex: [
            {
                validation: /^[a-z0-9]+$/i,
                message: language.passwordError
            }
        ],
        method: [
            {
                validation: (v) => {
                    const n = v.length;
                    return (n <= 20 && n >= 6);
                },
                message: 'Su contraseña debe ser de mínimo 6 elementos y máximo 20 elementos.'
            }
        ],
        compare: false
    },
    confirmation: {
        regex: [],
        method: [],
        compare: {
            value: 'password',
            message: 'La contraseña no coincide.'
        }
    }
});

Propiedades del objeto:

Propiedad Descripción
regex Array con los objetos que evalúan el valor del componente al que pertenece esta propiedad. La propiedad "validation" es el regex que se le aplica al valor y si no pasa su criterio, el mensaje de error que se muestra es la propiedad "message". Todas las validaciones de este array deben cumplirse para que no emita ningún error. En components.js hay ejemplos de uso para el error que se emite.
method Array con los objetos que evalúan el valor del componente al que pertenece esta propiedad. La propiedad "validation" es el método que evalúa el valor y si no pasa su criterio, el mensaje de error que se muestra es la propiedad "message". Todas las validaciones de este array deben cumplirse para que no emita ningún error. En components.js hay ejemplos de uso para el error que se emite.
compare Esta propiedad permite evaluar si el valor de un componente es igual al de otro. La propiedad "value" indica el "name" del componente cuyo valor debe ser igual al del componente con este mismo "name", en el ejemplo de arriba, los componentes con "name" igual a "confirmation" deben ser iguales a los que tengan "name" igual a "password"; sino, el mensaje de error que se envía es el valor de la propiedad "message". En components.js hay ejemplos de uso para el error que se emite.

components.js

Analice el siguiente ejemplo y preste atención a las notas:

import React from 'react';
import { View, TouchableOpacity, Button, TextInput, Text } from 'react-native';

export default ({ onForgetPassword }) => ({
    Container: ({ children }) => ( //Componente requerido: Es el wrapper de todo.
        <View style={{ width: 340, borderRadius: 8, padding: 16, marginBottom: 8, backgroundColor: '#A9A9A9' }}>
            {children}
        </View>
    ),
    Row: ({ children }) => ( //Componente requerido: Es el wrapper de los componentes horizontales.
        <View style={{ flex: 1, flexDirection: 'row' }}>
            {children}
        </View>
    ),
    Input: ({ data, configuration, method, error }) => ( //Componente requerido: Es el componente más común en un formulario.
        <View style={{ flex: 1, marginVertical: 8 }}>
            <Text style={{ fontWeight: 'bold' }}>{`${configuration.placeholder}${configuration.required ? ' *' : ''}`}</Text>
            <TextInput
                ref={method.ref}
                value={data.value}
                returnKeyType='next'
                onChangeText={data.onChange}
                onSubmitEditing={method.onSubmit}
                secureTextEntry={configuration.security}
                style={{ flex: 1, maxHeight: 40, borderColor: error ? 'red' : '#006400', borderWidth: 1 }} />
            {error ? <Text style={{ color: 'red' }}>{error}</Text> : null}
        </View>
    ),
    Forget: ({ data, configuration, method, error }) => (
        //Este es un ejemplo de un componente personalizado.
        <View style={{ flexDirection: 'row', marginBottom: 8 }}>
            <Text>{`${configuration.placeholder} `}</Text>
            <TouchableOpacity onPress={onForgetPassword}>
                <Text style={{ fontWeight: 'bold' }}>Toca aquí.</Text>
            </TouchableOpacity>
        </View>
    ),
    Button: ({ onPress }) => (
        //Componente requerido: Es el botón que se ubica al final del formulario
            //y ejecuta el método que envía la información del mismo, hay otras formas
                //de llamar al método "onFinish", pero quedan para otra versión de la documentación.
        <Button
            title="Listo"
            color="#006400"
            onPress={onPress}
            style={{ marginVertical: 16 }} />
    )
});

index.js

Analice el siguiente ejemplo y preste atención a las notas:

import React, { Component } from 'react';
import Form from 'react-native-baum-form';

import rules from './rules';
import structure from './structure';
import components from './components';

import language from '../../data/language';

export default (props) => {
    const FormInitialized = Form(structure, rules, components);
    //En este caso, concatenamos las propiedades que recibe este componente y le añadimos el lenguaje, es sólo un ejemplo de uso.
    return <FormInitialized {...{ ...props, language }} />
}

//También puede exportar directamente el formulario sin añadirle otras propiedades:
//export default Form(structure, rules, components);

//O puede exportarlo conectándolo a redux:
//export default connect(mapStateToProps, mapActionToProps)(Form(structure, rules, components));

//Las opciones son ilimitadas, sólo se debe jugar con la sintaxis.

Ejecución final

Analice el siguiente ejemplo y preste atención a las notas:

import React, { Component } from 'react';
import { ScrollView, View, StyleSheet } from 'react-native';

import Form from './components/Form';

const trollAlert = () => alert('Uy, que lástima xD');
const readyAlert = (obj) => {
  alert('Todo bien, mira la consola para ver el objeto que sale del form.');
  console.log('El form nos dio: ', obj);
};

//Por cierto: La dependencia no sólo facilita el crear formularios,
  //tiene muchas otras ventajas, por ejemplo... ¿Ya tocaste el botón "enter"
    //del teclado cuando terminas de escribir en el input?

export default () => (
  <ScrollView>
    <View style={styles.container}>

      <Form
        mode="LogIn"                  //Indica la estructura del formulario que se desea usar.
        onFinish={readyAlert}         //Es la función que se ejecuta cuando se presiona el botón del formulario y los datos pasan las reglas de rules.js
        onForgetPassword={trollAlert} //Esta propiedad se puede llamar como se desee, es sólo un ejemplo de “property” personalizado, en este caso así lo espera un componente en components.js
        />

      <View style={{ height: 2, width: 350, marginVertical: 32, backgroundColor: 'purple' }} />

      <Form
        mode="LogInConfirmation"      //Indica la estructura del formulario que se desea usar.
        onFinish={readyAlert} />

      <View style={{ height: 2, width: 350, marginVertical: 32, backgroundColor: 'purple' }} />

      <Form
        mode="Recover"                //Indica la estructura del formulario que se desea usar.
        onFinish={readyAlert} />

    </View>
  </ScrollView>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingVertical: 16,
    alignItems: 'center',
    backgroundColor: '#F5FCFF'
  }
});

Documentación demo, versión 0.0.11

License