1.8.2 • Published 1 year ago

@agtm/nuxt-form v1.8.2

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

nuxt-form

Nuxt Form tem como objetivo, facilitar a criação de formulários no nuxt(vue), simplificando e automatizando muitas tarefas repetitivas.

Conceitos chaves

O Nuxt form é composto por dois compoenentes principais:

Formulário (Form) e Campos (Field)

Caracteristicas

As principais caractéristicas do Nuxt Form são:

  • Integração completa com Nuxt
  • Integração com vuetify (a princípio) (se necessário adicionar outras bibliotecas no futuro)
  • i18n
  • Permitir criar formulários inteiros rapidamente através de uma descrição resumida em objetos ou json.
  • Ser flexivel permitindo criar qualquer tipo de formulário com qualquer tipo de campo, com minimo de restrições.
  • Modular, permite criar campos customizado facilmente (todos os campos são módulos do form)
  • Permitir usar campos individualmente, sem necessidade de instanciar um novo form aproveitando funcionalidades como máscara, validação entre outros...
  • Permitir gerar um formulário rapidamente através do schemas(json/objeto/nuxt-model) e com o tempo customiza-lo.
  • Funções comuns de formulários:
    • Validação (por campo e global)
    • Máscara
    • Habilitar/Desabilitar formulário
    • Foco em campo específico
    • loading (ex: aguardar submit)
  • Filtros de dados ()
  • Models Inteligente (Objeto que representa os dados do formulário)
    • Models aninhado (possibilidade de vincular um campo umatributo aninhado vários niveis dentro)
    • Integração com nuxt-model (em vez de passar um schema, lê o schema diretamente da class do Nuxt Model)

Documentação

Para devs: Manter esta documentação sempre atualizada com exemplos e refêrencias.

Instalação

Instale o seguinte pacote:

  npm install @agtm/nuxt-form

Adicione no arquivo nuxt.config.js:

modules: [
  [
    '@agtm/nuxt-form/nuxt',
    {
      nuxtI18n: true,
      language: 'pt-BR',
      debugger: false
    }
  ]
],

Com isso os componentes do nuxt-form já estarão disponiveis globalmente não havendo necessidade de importar novamente.

Primeiros passos

Para criar um formulário basta utilizar a tag nuxt-form como no exemplo:

<template>
  <nuxt-form v-model="formData">
    <nv-text-field
        field-name="name"
    />
    <nv-text-field
        field-name="lastname"
    />
  </nuxt-form>
</template>
<script>
export default {
  data() {
    return {
      formData: {
        name: 'André'
      }
    }
  }
}
</script>
  • Neste exemplo também criamos dois campo do tipo "caixa de texto" simples com nome "name" e "lastname".
  • Atributo "field-name" é obrigatório para que o formulário consiga identifica-lo
  • Os valores de todos os campos são acessados via "v-model" que é um atributo bidirecional.
  • Veja que definimos valores iniciais para o campo "name"

Podemos alterar os valores do formulário posteriormente (por exemplo, depois de uma consulta) há qualquer momento, para isto basta alterar "formData" que o formulário será atualizado imediatamente.

Importante: Todos os dados do formulário existentes serão perdidos. Para alterar alguns campos, utilize o método setModel via ref

Modo Stand Alone

É possivel utilizar os campos isoladamente, independente do formulário e aproveitando algumas de suas funcionalidades como validação e máscara, muito útil em alguns cenários:

<template>
  <nv-text-field
      v-model="standalone"
  />
</template>

<script>
export default {
  data() {
    return {
      standalone: 'stand_alone',
    }
  }
}
</script>

Notas:

  • Não é obrigatório definir "field-name" nestes casos.
  • Utilize v-model para acessar os dados do componente, como seria feito em input padrão do vue.
  • Não há necessidade de utilizar "v-model" em campos quando utilizar nuxt-form (modo completo).

TODO: Set error em modo stand alone???, TODO: validação em modo stand alone???

Schemas

Existem três modos de criar campos no "nuxt-form": via schema, slots ou nuxt-model.

Schemas são objetos no formato json que descreve todos os campos de um formulário, como nome, tipo, validação entre outros.

Por exemplo:

// TODO: Melhorar exemplo mais tarde, com mais atributos e tiṕo de campo
[
  {
    fieldName: 'name',
    fieldType: 'nv-text-field'
  },
  {
    fieldName: 'Name2',
    fieldType: 'nv-text-field'
  },
  {
    fieldName: 'Name3',
    fieldType: 'nv-text-field',
    validators: ['required', this.validation]
  }
]
  • No exemplo acima descrevemos 3 campos name, name2 e name3, do tipo texto simples
  • fieldName mapeia o nome do atributo definido no modelo (v-model) diretamente, então fieldName é importante para acesso aos dados
  • Schema foi criado tendo em mente velocidade de desenvolvimento, portanto todos os campos serão renderizados um embaixo do outro de forma simples. Para posicionar os campos ou criar layouts mais complexos utilize slots

Exemplo completo:

<template>
  <nuxt-form :schema="schema" v-model="formData"/>
</template>
<script>
export default {
  data() {
    return {
      formData: {},
      schema: [
        {
          fieldName: 'name',
          fieldType: 'nv-text-field'
        },
        {
          fieldName: 'Name2',
          fieldType: 'nv-text-field'
        },
        {
          fieldName: 'Name3',
          fieldType: 'nv-text-field',
          validators: 'required'
        }
      ]
    }
  }
}
</script>

Schema sempre deve estar no formato array, permitindo ordenar os campos conforme desejado

Slots

Outro modo de definir os campos do formulário é através de slots e pode ser feito de duas maneiras:

  • slot default
  • slot nomeado

Através de slots podemos utilizar campos customizados criado apenas no seu projeto.

Um exemplo de slot default é o exemplo mostrado no começo deste tutorial:

<template>
  <nuxt-form v-model="formData">
    <nv-text-field
        field-name="name"
    />
    <nv-text-field
        field-name="lastname"
    />
  </nuxt-form>
</template>
<script>
export default {
  data() {
    return {
      formData: {
        name: 'André'
      }
    }
  }
}
</script>

Modo Misto

Podemos criar no mesmo formulário, campos via schema ou via slots, desta forma podemos criar formulários rapidamente com esquema e no decorrer do projeto, graduamente, ir melhorando a implementação e substituíndo por campos definidos via slot.

Por exemplo:

<template>
  <nuxt-form :schema="schema" v-model="formData">
    <nv-text-field
        field-name="Name2"
    />
  </nuxt-form>
</template>

<script>

export default {
  data() {
    return {
      formData: {},
      schema: [
        {
          fieldName: 'name',
          fieldType: 'nv-text-field'
        },
        {
          fieldName: 'Name2',
          fieldType: 'nv-text-field'
        },
        {
          fieldName: 'Name3',
          fieldType: 'nv-text-field'
        }
      ]
    }
  }
}
</script>
  • Observe o campo "name2" ele é definido tanto no schema quanto no slot, neste caso a versão do slot tem precedencia, e o campo definido no schema é ignorado.

Slots Nomeados

Campos definidos via slot são renderizado acima dos campos definidos via schema, ou seja, se você criar um novo campo via slot a ordem de renderização será modificada.

  • Para não alterar a ordem definida via schema, podemos utilizar slots nomeados, que são renderizados na mesma posição definda em schema.
  • Porém, slots nomeados só funcionam se estiverem definidos em schemas, apenas o atributo fieldName no schema será aproveito, o restante será excluido.

Exemplo:

<template>
  <nuxt-form :schema="schema" v-model="formData">
    <template #Name3>
      <nv-text-field
          field-name="Name3"
      />
    </template>
  </nuxt-form>
</template>
<script>
export default {
  data() {

    return {
      formData: {},
      schema: [
        {
          fieldName: 'Name1',
          fieldType: 'nv-text-field'
        },
        {
          fieldName: 'Name2',
          fieldType: 'nv-text-field'
        },
        {
          fieldName: 'Name3',
          fieldType: 'nv-text-field'
        },

      ]
    }

  }
}
</script>

Nuxt Model

O Nuxt Form tem integração com o Nuxt Model, podemos passar uma instância de Model e gerar o form será gerado automaticamente a partir desse Model, além de manipular dados do model.

Exemplo de uso:

// aluno.model.js

import {Model} from '@agtm/nuxt-model'

export default class AlunoModel extends Model {
  static nameType = {
    type: 'string',
    fieldType: 'nv-text-field'
  }
}
  • Se alterarmos do tipo do atributo destring para objeto podemos definir ali qualquer atributo que seria defino no schema
<template>
  <div>
    <nuxt-form v-model="aluno" style="border: solid 1px">
    </nuxt-form>
    <v-btn @click="check">Check Model</v-btn>
  </div>
</template>

<script>
import AlunoModel from "@/models/aluno.model";

export default {
  data() {
    return {
      aluno: null
    }
  },
  created() {
    this.aluno = AlunoModel.create({name: 'João'})
    this.check()
  },
  methods: {
    check() {
      this.aluno.name = 'Maria'
    }
  }
}
</script>
  • Note que além do Model ser usado em substituição do Schema, ele também é usado em substituição de v-model.
  • A regra de prioridade de atributos do field é SLOT => SCHEMA => MODEL portanto é possivel sobrescrever atributos do model com schema ou slots.

Impedir que um campo do Model seja renderizado no formulário

Para não renderizar um campo no formulário use o atributo "hide" no schema:

{
  data()
  {
    return {
      schema: [
        {
          fieldName: 'id',
          hide: true
        }
      ]
    }
  }
}

Objetos Aninhados

Imagine a seguinte objeto de dados:

{
  "personal": {
    "name": "André"
  },
  "externo": [
    1,
    2,
    3,
    4
  ]
}

Agora imagine que você precise criar um campo para editar apenas o atributo "nome" dentro do objeto "personal" e não diretamente "personal"

Isso é feito facilmente definindo o nome do campo como "personal.name".

exemplo:

<template>
  <nuxt-form :schema="schema" v-model="formData">
    <nv-text-field
        field-name="personal.name"
    />
  </nuxt-form>
</template>

<script>

export default {
  data() {
    return {
      formData: {},
      schema: [
        {
          fieldName: 'personal.lastname',
          fieldType: 'nv-text-field'
        }
      ]
    }
  }
}
</script>
  • Desta forma apenas o atributo filho será alterado diretamente.
  • Se personal não estiver definido no modelo, então será criado automaticamente.

Acessando Métodos e atributos do formulários através de Ref

Para acessarmos os métodos do nuxt-form utilizamos "ref" como no exemplo abaixo:

<template>
  <div>
    <v-card>
      <v-container>
        <nuxt-form :schema="schema" v-model="formData" ref="form" @submit="submit">
        </nuxt-form>
        <v-btn @click="$refs.form.submit()">SUBMIT</v-btn>
      </v-container>
    </v-card>
  </div>
</template>

<script>
export default {

  mounted() {
    setTimeout(() => {
      this.$refs.form.setValues({name: 'André'})
    }, 3500)
  },
  data() {
    return {
      formData: {},
      schema: [
        {
          fieldName: 'lastname',
          fieldType: 'nv-text-field',
        }
      ]
    }
  },
  methods: {
    submit(valid, values, fields) {
      this.$refs.form.clearErrors()
      this.$refs.form.setErrors(['Erro Global'])
    }
  }
}
</script>

Validação

Validações são implementadas internamente no nuxt-form (utilizando o modulo validator) e também podem ser fácilmente customizadas.

Portando, podemos validar os campos de várias maneiras:

Validação Interna

São validações comuns implementadas internamente no nuxt-form, para definir uma validação interna simplemente defina o atributo "validators":

Exemplos:

<template>
  <nv-text-field
      field-name="name"
      validators="required"
  />
</template>

Caso queira mais de uma validação no mesmo campo:

<template>
  <nv-text-field
      field-name="name"
      :validators="['required', 'mustBeEmpty']"
  />
</template>

Se quisermos passar atributos para essa validação:

<template>
  <nv-text-field
      field-name="name"
      :validators="{validator: 'equal', options: {field: 'password', otherLabel: 'Confirme a Senha'}}"
  />
</template>

E por fim, podemos passar funções, veja mais detalhes em "validações Customizadas"

Caso esteja utilizando um schema, pode configurar validações da seguinte forma:

export default {
  data() {
    return {
      schema: [
        {
          fieldName: 'lastname',
          fieldType: 'nv-text-field',
          validators: ['required', this.validation]
        }
      ]
    }
  }
}

Validação Customizada

Para criar uma validação customizada, basta passar uma função no atributo "validators" do campo da seguinte forma:

export default {
  data() {
    return {
      schema: [
        {
          fieldName: 'lastname',
          fieldType: 'nv-text-field',
          validators: this.myValidation
        }
      ]
    }
  },

  methods: {
    myValidation(value, model) {
      return {valid: true}
    }
  }
}

A função criada terá os seguintes argumentos:

ArgumentoDescriçãoTipo
valueValor do campo no qual queremos validarAny
modelUma cópia do model do form, ou seja podemos acessar valores de qualquer outro campo. Exemplo: verificar se a senha preenchida pelo usuário em outro campo é idêntico a esteObject

IMPORTANTE: Validações podem ser assincronas (adicionar async na função customizada).

NOTA: Se utilizar a biblioteca validator, é necessário converter para string o valor recebido antes de validar

O mais importante é agora é o retorno, deve ser um objeto representando o resultado da validação e deve estar necessáriamente no seguinte formato:

Campo validado com sucesso:

return {valid: true}

Campo não válidado:

return {valid: false, error: 'VALIDATOR_REQUIRED'}

Note que além do status da validação, precisamos retornar uma mensagem de erro para ser exibida no formulário exatamente abaixo do campo inválido.

Porém, o que deve ser retornado em "error" é uma plavra-chave que represente a chave no arquivo de tradução. Veja mais detalhes em nuxt-i18n e vue-i18n, exceto se o modo internacionalização esteja desativado, neste caso é possível retornar a mensagem de erro diretamente

No exemplo acima 'VALIDATOR_REQUIRED' será traduzido para "campo obrigatório", caso o idioma esteja definido para pt-BR.

Mensagem de erro com váriaveis na tradução

Seguindo o nuxt-i18n, você pode utiizar váriaveis na tradução como no exemplo abaixo:

return {valid: false, error: 'VALIDATOR_EQUAL', errorValues: {same: model.otherLabel}}

Requisitar validação de outro campo

Em alguns casos, pode ser interessante sempre que este campo for validado, validar outros campo, como por exemplo na criação de nova senha, onde existe um segundo campo relacionado para confirmar senha. Para isso utilize o atributo " validate":

equal(value, model)
{
  const valueA = value || ''
  const valueB = model['confirmPassowrd'] || ''

  return valueA === valueB
    ? {valid: true, validate: 'confirmPassword'}
    : {valid: false, error: 'Campo inválido', validate: 'confirmPassword'}
}

Validação de Campo

Existem alguns tipos de campos, que requerem validações especiais que só servem pra este campo em específico. Neste caso a validação é implementada diretamente na implementação do campo customizado.

Segue as mesmas regras de validação customizada.

Leia mais na sessão: "Criando campos Customizados"

Validação Global

Em alguns casos, precisamos criar validações mais customizadas, exclusiva para o nosso formulário como um todo.

Por exemplo, caso o campo A do formulário for maior que 10, e o campo B estiver verdadeiro, então validar campo C

Para estes casos, o trabalho será manual, podemos criar um código de validação e manipular as mensagens de erros logo depois do evento submit do formulário.

Exemplo:

<template>
  <nuxt-form :schema="schema" ref="form" @submit="onSubmit"></nuxt-form>
</template>
<script>
export default {
  methods: {
    onSubmit(valid, values, fields) {

      if (valid) {
        /* NOSSA LOGÌCA DE VALIDAÇÂO AQUI*/


        if (error) {
          // Mensagem de erro em um campo
          fields.fieldA.setErrors(['Campo inválido'])
          fields.fieldA.addError('Campo inválido')

          // Mensagem de erro global
          this.$refs.form.addError('Este formulário tem um problema')
        } else {
          /* ENVIA DADOS PARA O BACKEND */
        }
      }
    }
  }
}

</script>

Outro exemplo muito comum, são erros vindo do backend, que deverão ser setados no formulário por aqui.

Modos de validação

A validação no formulário pode funcionar de diferentes maneiras. Podemos configura-la através da prop "validationMode".

Isso pode ser feito tando ao criar formulário ou ao criar um campo no modo standalone. Tempos 5 tipos para o modo formulário e 3 tipos para o modo standalone.

No modo formulário podemos ter:

ModoDescrição
onChangeValidação é executada sempre que o valor de um campo é alterado, validação em tempo real. Pode ser lento para formulários grandes.
onBlurValidação é executada sempre que um campo perde o foco
onBlurOrInvalidValidação é executada sempre que um campo perde o foco ou quando esta inválido (ou seja, em tempo real para remover mensagem de erro antes possível)
onSubmitValidação só é executada quando usuário submeter o formulário (Mais rápido, usa pouco processamento, útíl em formulários com muitos campos)
onSubmitOrInvalidValidação é executada quando usuário submete o formulário ou quando está inválido. (ou seja, em tempo real para remover mensagem de erro antes possível)

No modo standAlone teremos apenas os modos onChange, onBlur e onBlurOrInvalid

TODO: Debugger

TODO: Refêrencia de campos

TODO: i18n

-TODO: Criar arquivos com traduções padrão, para ser mesclado pelo usuario no i18n, porém usuario deve fazer manualmente,explicar como

Rêferencias

Opções do Módulo

AtributoDescriçãoPadrão
debuggerModo depuração, exibe borda vermelha nos componentes internos e exibe informações sobre componentes.true
nuxtI18nHabilita suporte ao plugin do nuxt: nuxt-i18n deve estar instalado no projeto, veja documentação em: https://pt.nuxtjs.org/docs/2.x/get-started/installation Necessário carregar arquivos de tradução do formulário em seu projeto localizado em @agtm/nuxt-form/src/langfalse
languageIdioma utilizado caso não queira utilizar o modulo "nuxt-i18n". Caso precise da funcionalidade de idioma dinâmico necessário utilizar o "nuxt-i18n". Por enquanto apensar idioma pt-BR está disponível'pt-BR'

Table Editor: https://www.tablesgenerator.com/markdown_tables

Props

PropTipoPadrãoDescrição
schemaArray[]Descreve os campos do formulário (formato json) mapeia campo com dado.
valueObject || InstanceOf NuxtModel{}Representa os dados de todos os campos do formulário, obrigatório ser objeto ou instancia de nuxt-model
validationModeStringonChangeModo de validação onChange, onBlur, onBlurOrInvalid, onSubmit, onSubmitOrInvalid
disableFieldsUpdateByVModelBooleantruePor padrão ao alterar valor de v-model, todos os campos tem seus valores sincronizados com model do formulário Porém, isto causa um efeito colateral, sempre que um campo altera seu valor, todo formulário é atualizado novamente, podendo causar lentidão em formulários muito grande. Utilize esta opção para melhorar performance nesses casos.
cleanNullValuesOnSubmitBooleantrueAo carregador valores dos campos ou ao submeter formulário, atributos com valor null, undefined ou objeto vazio {}, são removidos do resultado final. y

Eventos

submit

Disparado quando usuario submete o form

Enviado parametro:

isValid (formulário validado) values (lista de valores) fieldsComponentIndex (acesso a todas as instancias de campos do form)

TODO: enviar parametro instancia de form

ready

Disparado quando o formulário tá renderizado e carregado

Enviado parametro form (instancia de form)


Métodos

Métodos para manipulação do formulário, pode ser acessado com $refs

Exemplo:

mounted() {
  this.$refs.form.setValues({name: 'André'})
}

ATENÇÃO: No vuefile, é os métodos só podem ser chamados depois da renderização do formulário, ou seja, não irá funcionar no lifecycle hooks beforeCreated, creted ou beforeMount

clearErrors

Limpa todas as mensagens de erros customizados no campo e erros definidos globalmente

IMPORTANTE: Não limpa erros de validações internas (ex: required)

isValid

Verifica se o formulário é válido

IMPORTANTE: Não valida formulário, simplesmente retorna o resultado da última validação. Se tiver utiizando o modo " submit" ou "onSubmit" será necessário executado o método "validate()" antes.

Retorno (boolean) Se formulário está válido ou não

setErrors

Atribui mensagens de erros globais, limpa mensagens de erros antigos.

ParâmetroDescriçãoTipo
errorsLista de mensagens de erroString[]

addError

Adiciona uma menagem de erros global, adiciona um erro sem limpar erros atigos

ParâmetroDescriçãoTipo
errorsMensagem de erroString

setValues

Atribui valores aos campos do formulário (model). Só altera os campos definidos em "values" ao contrário de alterar v-model que limpa os valores de todos os campos antes de atrabituir (substitui).

ParâmetroDescriçãoTipo
valuesObjeto com nome do campo e valor a ser atribuidoObject

Retorno: void

submit

Utilizado quando se deseja submeter os dados do formulário, esta operação, executa validação completa e disapara o evento "submit"

Por exemplo, ao submeter o formulário para o backend, execute o metodo submit() e no evento submit, verificamos validação dos campos, realizamos validações extras.

(async) validate

Executa validação do formulário

ParâmetroDescriçãoTipoPadrão
fieldsNameLista com nome dos campos que serão validadosString[]Todos os campos
validatedFieldsLista de nome de campos que já foram validados. Usado internamente, quando o campo A requisita validação de B e B requisita de A, evita "loop infinito".string[][]

Retorno: void (Utilize o método "isValid", para saber se o formulário está válido)

Métodos de Campos

Para ter acesso a estes métodos. necessário te a lista de componentes do formulário, isso pode ser feito através do evento "submit".

Veja mais detalhes no evento submit

setErrors

Define todas as mensagens de erro customizada para este campo. Erros de validações internas são mescladas com esta lista. Usado principalmente em conjunto com o evento "submit" para criar validações customizadas ou criar mensagem de erros vindo do backend

NOTA: Também é possível pode manipular lista de erros através da prop "errors" do campo (quanto componente é definido via slots)

1.8.2

1 year ago

1.8.1

1 year ago

1.8.0

1 year ago

1.7.1

1 year ago

1.7.0

2 years ago

2.0.0

2 years ago

1.6.7

2 years ago

1.6.6

2 years ago

1.6.5

2 years ago

1.2.0

2 years ago

1.6.2

2 years ago

1.6.1

2 years ago

1.6.0

2 years ago

1.5.0

2 years ago

1.4.1

2 years ago

1.4.0

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

1.0.10

2 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.2

3 years ago

1.0.3

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago