O esquema do FormKit é um formato de dados serializável em JSON para armazenar estruturas DOM e implementações de componentes, incluindo formulários do FormKit. Embora criado especificamente para implementar e gerar formulários, o formato é capaz de gerar qualquer marcação HTML ou usar quaisquer componentes de terceiros.
Esquemas são renderizados usando o componente <FormKitSchema>
do FormKit, que não é registrado globalmente por padrão. Você precisará importá-lo:
import { FormKitSchema } from '@formkit/vue'
O FormKit vem com suporte de primeira classe para gerar formulários usando esquema. Isso torna possível armazenar formulários gerados em bancos de dados, arquivos ou até mesmo códigos QR! Para gerar um formulário, passe sua matriz de esquema para o componente <FormKitSchema>
usando a propriedade :schema
.
<FormKitSchema :schema="yourSchemaArray" />
Vamos olhar um exemplo rápido:
Vemos muitos recursos acima, incluindo as propriedades $el
e $cmp
, o atalho da propriedade $formkit
, validação, renderização condicional, rótulos, texto de ajuda e vários tipos de entradas. Vamos desempacotar todos esses recursos no restante desta página.
Um esquema é uma matriz de objetos ou strings (chamados de "nós de esquema"), onde cada item da matriz define um único nó de esquema. Existem 3 tipos de nós de esquema:
$el
.$cmp
.$formkit
. Açúcar sintático para o formato completo $cmp
.Esquemas suportam recursos avançados como lógica condicional, operadores booleanos, laços, slots e escopo de dados — todos garantidos para serializar em uma string.
Elementos HTML são definidos usando a propriedade $el
. Você pode usar $el
para renderizar qualquer elemento HTML. Atributos podem ser adicionados com a propriedade attrs
, e o conteúdo é atribuído com a propriedade children
:
Note no exemplo acima que o atributo style
é único no sentido de que deve ser definido como um objeto de pares de estilo para valor em vez de uma string.
Componentes podem ser definidos com a propriedade $cmp
. A propriedade $cmp
deve ser uma string que referencia um componente globalmente definido ou um componente passado
para FormKitSchema
com a prop library
:
Para passar componentes concretos via prop library
, é melhor envolver sua biblioteca com a assinatura markRaw
do Vue.
Além do array de esquema (e da biblioteca opcional), o objeto FormKitSchema
também pode incluir uma prop data
. Valores do objeto data podem então ser referenciados diretamente no seu esquema — e seu esquema manterá a reatividade do objeto de dados original.
Para referenciar um valor do objeto data, você simplesmente usa um cifrão $
seguido pelo nome da propriedade do objeto de dados. Referências podem ser usadas em attrs
, props
, condicionais e como children
:
Note no exemplo acima que usamos um array para concatenar "Hello" e "$location". Fizemos isso porque referências de dados e expressões lógicas no esquema devem sempre começar com um cifrão $
— caso contrário, são tratadas como literais de string não analisadas.
Esquemas suportam a chamada de funções que estão nos seus dados de referência originais — e você pode até passar referências de dados como argumentos dessa função!
Assim como em JavaScript — você pode acessar propriedades de um objeto profundamente aninhado usando a sintaxe de ponto object.property
:
Referências de esquema podem ter qualquer estrutura ou propriedades, mas na raiz do objeto de referência de dados existem 2 palavras reservadas: $slots
e $get
.
Esquemas também suportam lógica na forma de lógica booleana, comparação e expressões aritméticas. Essas expressões podem ser usadas em qualquer lugar onde uma referência de dados possa ser usada (attrs
, props
, condicionais e children
):
Expressões devem sempre começar com um $
. Se o primeiro elemento de uma expressão é uma referência de dados (ex: $count + 2
), então ela já começa com um $
e nenhum outro rótulo é necessário. No entanto, muitas vezes o primeiro caractere de uma expressão não é um cifrão — essas expressões precisam ser "rotuladas" com $:
— por exemplo $: ($count * 3) - 7
.
Embora pareça muito com JavaScript — expressões de esquema não são JavaScript. É melhor pensar nelas como uma linguagem de template. Expressões são compiladas para JavaScript funcional no setup
, mas a sintaxe não é compatível 1-1 com JavaScript. Isso melhora o desempenho e fornece uma camada crítica de segurança, pois apenas dados e funcionalidades explicitamente expostos podem ser executados.
Expressões de esquema são limitadas aos seguintes operadores e parênteses:
Operador | Caso de uso |
---|---|
+ | Adição |
- | Subtração |
* | Multiplicação |
/ | Divisão |
% | Módulo |
&& | E lógico (AND) |
|| | OU lógico (OR) |
=== | Igualdade estrita |
!== | Desigualdade estrita |
== | Igualdade solta |
!= | Desigualdade solta |
>= | Maior ou igual |
<= | Menor ou igual |
> | Maior que |
< | Menor que |
O esquema do FormKit pode aproveitar referências e expressões para tornar nós e atributos do esquema condicionais. Esses condicionais podem ser adicionados de duas maneiras:
if
nos nós $el
e $cmp
.if/then/else
if
Tanto os nós de esquema $el
quanto $cmp
podem aproveitar uma propriedade if
que se assemelha aproximadamente a um v-if
no Vue. Se a expressão atribuída à propriedade if
for verdadeira, o nó é renderizado, caso contrário, não é:
Nós de esquema condicionais ou iterativos (quando usando if
ou for
) devem sempre incluir uma propriedade key
explícita. Sem essa propriedade, o Vue pode reutilizar os nós do DOM da renderização anterior, o que pode levar a comportamentos inesperados, erros e problemas de desempenho.
if/then/else
O objeto if/then/else
permite uma lógica condicional mais complexa. Ele pode ser usado para renderizar condicionalmente nós, uma lista de nós de esquema, valores do objeto attrs
ou valores do objeto props
. Também é possível aninhar objetos if/then/else
para criar estruturas mais complexas — semelhante a uma declaração else if
em JavaScript.
if/then/else
em nós de esquemaVocê pode usar o objeto if/then/else
em qualquer lugar onde normalmente usaria um nó de esquema. Isso inclui o array de esquema raiz ou a propriedade children
de outro nó de esquema:
Nós de esquema condicionais ou iterativos (quando usando if
ou for
) devem sempre incluir uma propriedade key
explícita. Sem essa propriedade, o Vue pode reutilizar os nós do DOM da renderização anterior, o que pode levar a comportamentos inesperados, erros e problemas de desempenho.
if/then/else
em attrs e propsVocê também pode usar declarações if/then/else
para produzir condicionalmente os valores de attrs
ou props
:
Tanto os nós de esquema $el
quanto $cmp
suportam laços. A sintaxe do laço é semelhante a v-for
no Vue e espera um objeto ou array para iterar e uma propriedade para atribuir o valor da iteração atual. Opcionalmente, você também pode capturar o índice ou a propriedade da iteração atual:
Nós de esquema condicionais ou iterativos (quando usando if
ou for
) devem sempre incluir uma propriedade key
explícita. Sem essa propriedade, o Vue pode reutilizar os nós do DOM da renderização anterior, o que pode levar a comportamentos inesperados, erros e problemas de desempenho.
Esquemas podem renderizar o conteúdo do slot do componente <FormKitSchema>
em qualquer lugar dentro do esquema onde um nó de esquema normal possa ser renderizado. Todos os slots com escopo são automaticamente fornecidos ao esquema sob o objeto de referência $slots
:
Dentro de um nó de esquema $formkit
, também é possível passar conteúdo para slots preexistentes do FormKit como label
ou prefix
dentro da propriedade do nó __raw__sectionsSchema
. Leia mais sobre valores brutos abaixo, e sectionsSchema
na documentação de entradas.
Às vezes pode ser necessário passar um objeto de atributos ou props variáveis ou desconhecidos para um $cmp
ou $el
. No Vue faríamos isso usando v-bind
— no mundo dos esquemas usamos a propriedade bind
:
Às vezes pode ser necessário impedir que um dado atributo ou prop seja analisado. Isso pode ser feito prefixando um atributo ou prop com __raw__
:
{
$cmp: 'PriceComponent',
props: {
__raw__price: '$2.99'
}
}
No exemplo acima, o prefixo __raw__
será removido, e o valor não analisado de $2.99
será passado como a prop price
para o PriceComponent
.
Outro cenário onde isso é útil é na renderização de componentes FormKit. O componente <FormKit>
tem uma prop sections-schema
que permite aos usuários passar partes de esquemas para mesclar com várias seções de sua entrada. Neste caso específico, queremos passar os pedaços do esquema para o componente <FormKit>
como um objeto JavaScript bruto. Para fazer isso, mais uma vez prefixamos a prop sectionsSchema
com __raw__
:
Note que se você remover o prefixo __raw__
do exemplo acima, o prefixo não terá mais efeito — isso ocorre porque o valor da prop sectionsSchema
foi analisado ao criar o componente em vez de ser passado como um objeto JavaScript.
Embora os esquemas possam ser usados para quase qualquer finalidade — o objetivo principal é capacitar os desenvolvedores a construir formulários complexos e dinâmicos usando um formato de dados serializável. Usar o esquema com as Entradas FormKit cobre bem esse caso de uso.
Assumindo que você registrou globalmente o componente FormKit
— você pode renderizar suas entradas FormKit
a partir do esquema usando o nó de esquema do tipo $cmp
:
Embora a sintaxe cmp
seja generalizada e funcione para qualquer componente Vue, ela é um tanto verbosa para os Inputs do FormKit. Para facilitar isso, o FormKit suporta um quarto tipo de nó $formkit
, que é um açúcar sintático para o formato completo $cmp
.
Ao usar a abreviação $formkit
, o objeto props
é achatado com as propriedades de nível superior (irmãos de $formkit
) Por exemplo:
O formato do esquema tem uma função embutida específica para os Inputs do FormKit: a função $get
. Esse builtin permite que o esquema acesse o objeto de contexto de qualquer outro Input do FormKit (mesmo fora do formulário imediato) — desde que o input em questão tenha uma propriedade id
explicitamente declarada. Isso permite que o esquema responda condicionalmente ao estado dos seus próprios inputs:
Para renderizar um elemento de formulário, você pode usar o nó de esquema $formkit: 'form'
, ou envolver seu componente <FormKitSchema>
em um componente <FormKit type="form">
: