1.4.2 • Published 3 years ago

dinamicform v1.4.2

Weekly downloads
38
License
MIT
Repository
github
Last release
3 years ago

Instalação

    npm install --save dinamicform

DEMO

O que é o dinamicform ?

imagem de exemplo

Beleza, sendo bem breve, esse componente serve para você criar formulários usando apenas json, é um workhorse, ficou confuso? calma que daqui a pouco você irá vê um exemplo. Atualmente com a demanda de tempo sendo grande em muitas empresas e os devs estando cada vez mais na correria, surge necessidade de padronização e fácil utilização de certos componentes, imagina você fazendo um formulário de 30 campos, kkkk nunca vi um assim, mas supondo que exista, escrever tudo na mão é meio cansativo; é aí que entra o dinamicform, ele irá te ajudar a acelerar o processo, segue um exemplo básico abaixo.

    {
        col:6,
        type:'text',
        name:'name',
        label:'Nome',
        placeholder:'Escreva seu nome'
    },
    {
        col:6,
        type:'text',
        name:'surname',
        label:'Sobrenome',
        placeholder:'Escreva seu sobrenome'
    },
    {
        col:6,
        type:'text',
        name:'cpf',
        label:'CPF',
        format:'###.###.###-##',
        placeholder:'Digite seu cpf'
    }
    ...

Como configurar?

certo, chega de babozeira e vamos para a documentação profunda, como ele é um pacote bem completo, iremos passo a passo, do básico ao avançado. Aqui nessa configuração você vai definir os tipos de campo que você irá usar em sua aplicação e os componentes correspondentes a eles. Abaixo há um exemplo, com um input tag bem simples para você entender o conceito.

    // ./Form.config.js
    import React, {forwardRef, Fragment} from 'react';
    import Form from 'dinamicform';

    //forwardRef é opcional
    export default forwardRef(Form.bind(({
        props,
        errors,
        values,
        changeValue,
        submit,
        clean,
        getAllFields
    }) => ({
        breakpoints:{
            xs: 0,
            sm: 600,
            md: 960,
            lg: 1280,
            xl: 1920
        },
        errors:[
            field => {

                let {required, name} = field;
                let value = values[name];
                if(required && !value){
                    return 'Campo Obrigatório';
                }
            }
        ],
        onError:err => console.log(err),
        components:[
            {
                type:'default',
                contentProps:{}, // passo props para a tag pai desse campo, nesse caso, é uma grid coluna
                content: field => (
                    <Fragment>
                            <label>{field.label}</label>
                            <input 
                                type={field.type} 
                                value={values[field.name]||''} // recomendo colocar o ||<formato do campo -> string|array|boolean/> caso contrário esse componente pode apresentar falhas; errado: value={values[field.name]}; certo: value={values[field.name] || []}
                                onChange={evt => {
                                    changeValue(field.name, evt.target.value)
                                }} 
                                name={field.name}
                                placeholder={field.placeholder}
                                style={{width:'100%'}}
                            /> 
                            <span style={{color:'red'}}>{errors[f.name]}</span>                     
                    </Fragment>
                )
            }
        ],
        button:(
            <button onClick={submit}> Salvar </button>
        )
    })));

parâmetros de configuração:

nometipodescrição
breakpointsjsonPor padrão é os valores que você vê acima, aqui você pode configurar os breakpoints de sua aplicação, deixando-a responsíva.
errorsarrayretorna um array de funções responsáveis por customizar os erros do formuláro, você pode criar seus próprios erros customizáveis, como no exemplo acima, tem uma função que valida de forma básica se os campos que tem o atributo required está vazio ou não.
onErrorfunctonfunção de evento, dispara toda vez que o formulário é submetido, porém se ainda encontrar erro em algum campo esse ouvinte retorna um array de campos invalidos e suas respectivas mensagens de erro, exemplo: [{name:'Campo Obrigatório'}, {username:'Formato Inválido'}]
componentsarrayesse é o principal, aqui você coloca seus campos customizáveis, em cada json, temos o type: o tipo do campo, você também pode passar múltiplos types type: ['default', 'text'] content: o conteúdo, o componente de campo em si.
buttonjsx/htmlcampo de submição do formulário.

parâmetros de retorno da função em bind:

nometipodescrição
propsjsonretorna todas as props passadas no componente <Form .../>
errorsarrayretorna todos os campos e seus respectivos erros, exemplo: [{name:'Campo Obrigatório'}, {username:'Formato Inválido'}]
valuesjsonretorna os valores do formulário.
changeValuefunctionfunção responsável por mudar um determinado campo do formulário changeValue(<nome do campo>, <valor>, <qualquer coisa>) o terceiro parámetro será ouvido no onChangeField(field, value, qualquer coisa) que você verá logo a seguir
submitfunctionfunção responsável pelo envio do formulário, não aceita parâmetro algum nem tem retorno.
cleanfunctionfunção responsável por limpar o formulário, não aceita parâmetro algum nem tem retorno.
getAllFieldsfunctionretorna todos os campos do formulário.

Como usar ?

começando:

Abaixo tenho o caso de uso com todas as props sendo passadas, use as que você achar necessárias. Você também pode passar suas próprias props personalizadas e pegar em Form.config.js para fazer algo, mas cuidado, use com sabedoria.

    // ./index.js
    import Form from './Form.config.js';

    <Form
        values={{name: 'Rodrigo', user: 'rodrigo@email.com'}} 
        fixedValues={{tel:01589999888888}}
        spacing={2}
        alignItems='flex-start'
        justify={/*...*/}
        alignContent={/*...*/}
        direction={/*...*/}
        ref={/*...*/}
        innerRef={/*...*/}
        formData={false}
        init={form => console.log(form)}
        fields={[
            {
                col:4, //--é o mesmo que xs, padrão 12
                xs:4,
                sm:6,
                md:4,
                lg:3,
                xl:2,
                input(value){
                    /* retorno um valor de entrada*/
                    return value+'_1234' 
                    /* 
                        nesse caso, esse campo name irá mostrar Rodrigo_1234 na tag Input ou 
                        em qualquer outro componente de campo que você estiver usando
                    */
                },
                output(value){
                    /* retorno um valor de saída*/
                    return value+'_1234' 
                    /* 
                        nesse caso, quando você submeter o formulário ele irá mostrar: {name: 'Rodrigo_1234', user: 'rodrigo@email.com'}
                    */
                },
                error(e){
                    // retorno um erro personalisado somente para esse campo
                },
                type:'text',
                name:'name',
                label:'Nome',
                contentProps:{} // passo props para a tag pai desse campo, nesse caso, é uma grid coluna
            },
            {
                col:4,
                type:'text',
                name:'user',
                label:'Usuário',
                help:'Usuário do login',
            }
        ]}
        fixedFields={[
            {name:'nickname', required:true},
            {name: 'othername'},
        ]}
        onChangeField={(field, value) => console.log(field, value)}
        onSubmit={value => console.log(value)}
        beforeButton={<span>olá mundo</span>}
        afterButton={/*...*/}
        hiddenButtonSubmit={false}
        grid={{
            row:{/*...*/},
            col:{/*...*/}
        }}
        clean={false}
    />

Props:

nometipodescrição
valuesjsonaqui eu passo o valor inicial do formulário, útil quando queremos editar um formulário, caso for cadastro não precio passar essa props ou passo como um objeto vazio. Padrão undefined.
fixedValuesjsonvalores fixados, no momento da submição o formulário irá retornar os resultados dessa props também junto aos outros campos, no exemplo acima temos um número de telefone fictício.
spacingnumericPadrão: 2. Vai de 0 ao infinito, define o espaçamento das colunas. Internamente o formulário tem uma grid, podemos vê isso no col:4 explico sobre isso mais tarde.
alignItemsstringPadrão flex-start, este é o align-items do flexbox, você passa os valore que ele aceita
justifystringPadrão undefined, este é o justify-content do flexbox, você passa os valore que ele aceita
alignContentstringPadrão undefined, este é o align-content do flexbox, você passa os valore que ele aceita
directionstringPadrão undefined, este é o flex-direction do flexbox, você passa os valore que ele aceita
refpasso a referência do formulário para acessar certas propriedades.
innerRefcaso eu não comsiga usar o ref (tem casos assim), eu tenho o innerRef para aí sim me trazer o ref.
formDataBoleanpor padrão o onSubmit traz dados em json, mas se eu quiser trazer no formato form/data eu passo essa props.
initfunctionescuto todas as propriedades, e posso salvar em uma variável ou algo assim, não confundir com ref, são conceitos diferentes.
fieldsarraypasso os campos que quero no formulário.
fixedFieldsarraycampos fixados, são campos que já quero definir por padrão, a primeira vista não parece necessário mas em breve irão entender.
onChangeFieldarraytoda vez que um campo for alterado eu escuto ele por aqui.
onSubmitcallbackescuto a submição do formulário.
_onSubmitcallbackdispara independente se o formulário tem erro ou não, é diferente do onSubmit (esse só dispara se todos os campos estiverem validados, sem mensagens de erro)
beforeButtonpasso qualquer coisa para ser renderizado antes do botão do formulário.
afterButtonpasso qualquer coisa para ser renderizado depois do botão do formulário.
hiddenButtonSubmitBooleandefine se quero esconder os botões e seus irmãos beforeButton, afterButton. Padrão undefined.
gridjsonpasso props para a grid, no row tenho as props para as linhas e no col tenhos as props para colunas.
cleanBooleandefino se quero ou não que o formulário seja limpo automaticamente depois da submição.Padrão false.

Casos de uso:

Se eu quero definir um campo como obrigatório eu passo required: true

{
    col:9,
    type:'text',
    name:'name',
    required:true,
    /*...*/
},

posso também passar props para a coluna do meu campo

    {
        col:9,
        type:'text',
        contentProps:{
            style:{
                background:'blue'
            }
        },
        /*...*/
    },

As vezes não quero usar um campo, mas quero customizar ou apenas usar um conteúdo qualquer no formuláro. Então eu passo assim:

    {
        /*...*/
    },
    {
        //esse tipo de campo já está embutido no dinamicform, você não precisa criar entre seus campos customizados
        col:12,
        type:'component',
        content:(evt)=>(
            <div>
                este hr é somente para separar um campo do outro
                <hr/>
            </div>
        )
    },
    {
        /*...*/
    },

o content retorna: (todas as props, changeValue, submit, clean(), fields, getAllFields())

Eu também posso passar props dentro dos fields json, e pegar elas em Form.config.js. No exemplo abaixo suponhamos que eu tenha um component de select criado lá no arquivo de configuração, eu vou querer passar options para ele, correto? então faço assim:

    {
        /*...*/
    },
    {
        col:9,
        type:'select',
        options:[
            {value:1, label:'Opção 1'},
            {value:1, label:'Opção 2'},
        ],
        /*...*/
    },
    {
        /*...*/
    },

No Form.config.js na parte de components, no campo de type igual a select pego field.options

As vezes quero englobar um campo por um wrap.

    {
        /*...*/
    },
    {
        wrap(children){
            <div style={{
                backgroundColor:'#92d050', 
                padding:20,
                borderRadius:10
            }}>
                {children}
                <span>Olá mundo</span>
            </div>
        },
        col:9,
        type:'select',
        /*...*/
    },
    {
        /*...*/
    },

Exemplo usando wrap props

Eu posso também criar linhas e colunas por aqui, quando eu tiver um fields props dentro do json, significa que quero usa-lo como uma linha, e no array escrevo as colunas.

    {
        /*...*/
    },
    {
        wrap(){/*...*/}, //posso passar um wrap para a linha se eu quiser também
        col:6,
        fields:[
            {
                col:6,
                type:'text',
                /*...*/
            },
            {
                col:6,
                type:'text',
                /*...*/
            }
        ]
    },
    {
        col:6,
        fields:[
            {
                col:6,
                type:'text',
                /*...*/
            }
            {
                col:6,
                type:'text',
                /*...*/
            }
            {
                col:6,
                type:'text',
                /*...*/
            }
        ]
    },
    {
        /*...*/
    },

Quase todo formulário tem um select, e em muitos casos um campo de seleção depende de outro, por exemplo, ao selecionar um estado queremos carregar as cidades daquele estado em outro campo de seleção para o usuário escolher. Suponhamos que esses dois campos são obrigatórios e que um usuário selecione um estado e uma cidade, mas logo depois mude o valor novamente do campo estado, em teoria o campo cidade deve se limpar também, caso contrário enviariamos dados errado para o servidor. Automaticamente isso não acontece, precisamos informar ao formulário qual campo depende de outro, então passamos um atributo chamado dependence: <indicador>-<ordem>

    {
        col:6,
        name:'country',
        options:[/*...*/],
        dependence: 'snack-1'
    },
    {
        col:6,
        name:'state',
        options:[/*...*/],
        dependence: 'snack-2'
    },
    {
        col:6,
        name:'city',
        options:[/*...*/],
        dependence: 'snack-3'
    },

o atributo é dependence: <indicador>-<ordem> aqui nesse exemplo coloquei "indicator" como snack (você escolhe o nome, é para diferenciar caso haja outros campos com outras dependência) e em seguida coloquei a ordem de dependência, significa que o campo city depende do campo state que depende do campo country, ou olhando de forma inversa, country é superior a state que é superior a city, vai do menor para o maior. assim, toda vez que eu mudar o campo country por exemplo, o campo state e city irão limpar seus valores. Recomendo ver na prática.

Funções utilitárias:

debounce

    import {debounce} from 'dinamicform';
    /*...*/
    let change = useMemo(() => debounce(evt => console.log(evt), 400), [...]); //atraso de 400ms
    /*...*/
    <input type='text' onChange={change}/>

Fim

Bom, por enquanto é isso, espero que eu não esteja esquecendo de nada kkk, quem quiser contribuir, comentar algo, segue meu repositório. Ah sim, versão estável a partir da 1.2.3, as anteriores eram testes no npm. Em breve estarei colocando uma pasta de exemplos.

1.4.2

3 years ago

1.4.1

3 years ago

1.3.7

3 years ago

1.3.6

3 years ago

1.4.0

3 years ago

1.3.9

3 years ago

1.3.8

3 years ago

1.3.5

3 years ago

1.3.4

3 years ago

1.3.3

3 years ago

1.3.2

3 years ago

1.3.1

3 years ago

1.3.0

3 years ago

1.2.9

3 years ago

1.2.8

3 years ago

1.2.7

3 years ago

1.2.6

3 years ago

1.2.5

3 years ago

1.2.4

3 years ago

1.2.0

3 years ago

1.2.3

3 years ago

1.2.2

3 years ago

1.2.1

3 years ago

1.1.9

3 years ago

1.1.8

3 years ago

1.1.7

3 years ago

1.1.6

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.9

3 years ago

1.0.2

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago