A validação de formulário é parte integrante da maioria dos aplicativos e também uma ferramenta essencial no arsenal de qualquer desenvolvedor de aplicativos móveis. Com o advento do Flutter e sua popularidade crescente, exploraremos como a validação de formulário funciona no Flutter e alternativa maneiras de fazer com que funcione melhor.

O objetivo deste artigo é fornecer a você uma ampla compreensão de como funciona uma implementação limpa e escalonável de validação de formulário no Flutter. No final desta postagem do blog, você poderá aplicar os conceitos a todos os seus futuros projetos de desenvolvimento de aplicativos.

Introdução à validação de formulário no Flutter

O Flutter SDK nos fornece um widget pronto para uso e funcionalidades para tornar nossas vidas mais fáceis ao usar a validação de formulário. Neste artigo, cobriremos duas abordagens para validação de formulário: o widget de formulário e o pacote do provedor . Você pode encontrar mais informações sobre essas duas abordagens nos documentos oficiais do Flutter.

Criando um formulário no Flutter

Validação de formulário

Formulário vazio

Primeiro, vamos criar uma página de login simples com os seguintes campos:

  • Email
  • Nome
  • Número de telefone
  • senha

Formulário sendo preenchido

Para a validação, queremos que os usuários de nosso aplicativo preencham detalhes inválidos em cada um desses campos, para que a lógica seja definida conforme abaixo.

  • E-mail: queremos um e-mail válido que contenha alguns caracteres antes do sinal “@”, bem como o domínio do e-mail no final do e-mail.
  • Nome: queremos que o usuário insira um nome e sobrenome válidos, que também podem ser acompanhados pelas iniciais.
  • Número de telefone: para validação do número de telefone, o usuário deve inserir 11 dígitos começando com o dígito “0”.
  • Senha: para nossa validação de senha, esperamos que o usuário use uma combinação de uma letra maiúscula, uma letra minúscula, um dígito e um caractere especial.

Somente quando a entrada do usuário corresponder ao mencionado acima, queremos aceitar sua entrada antes de fazer qualquer solicitação, como enviar para um servidor ou salvar em um banco de dados.

Usando métodos Regex e métodos de extensão Dart

Para tornar nossas vidas mais fáceis e evitar escrever várias declarações if-else, vamos empregar o uso de Regex (Expressão regular) e Métodos de extensão do DART em nosso aplicativo.

Comece criando um novo projeto Flutter no Vscode ou no Android Studio. Você pode verificar aqui para começar a criar um novo projeto Flutter.

Substitua o aplicativo de contador padrão Flutter por seu próprio widget com estado. Você deve ter algo assim:

 import'package: Flutter/material.dart'; import'form/form_page.dart'; void main () { //runApp (Provider (create: (_)=> FormProvider (), filho: MyApp ())); runApp (MyApp ());
} class MyApp extends StatelessWidget { //Este widget é a raiz do seu aplicativo. @sobrepor Construção de widget (contexto BuildContext) { return MaterialApp ( título:'Demonstração de validação de formulário', tema: ThemeData ( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: FormPage (), ); }
}

Esta é a aparência do nosso arquivo main.dart atualmente. Agora, crie um novo arquivo dart com o nome form_page.dart e crie o widget FormPage com estado dentro dele.

Vamos criar uma classe de extensão que conterá todos os métodos de extensão que usaremos neste tutorial.

extensão

 extString na String { bool get isValidEmail { emailRegExp final=RegExp (r"^ [a-zA-Z0-9.] + @ [a-zA-Z0-9] + \. [a-zA-Z] +"); return emailRegExp.hasMatch (this); } bool get isValidName { nome finalRegExp=novo RegExp (r"^ \ s * ([A-Za-z] {1,} ([\.,] | [-'] |)) + [A-Za-z] + \.? \ s * $"); return nameRegExp.hasMatch (this); } bool get isValidPassword { senha finalRegExp=novo RegExp (r'^ (?=. *? [AZ]) (?=. *? [az]) (?=. *? [0-9]) (?=. *? [! @ # \ $ & * ~]). {8,} $'); retornar passwordRegExp.hasMatch (this); } bool get isNotNull { retornar isso!=null;
} bool get isValidPhone { final phoneRegExp=RegExp (r"^ \ +? 0 [0-9] {10} $"); return phoneRegExp.hasMatch (this); } }

Observação: para o escopo deste artigo, não perderemos muito tempo elaborando métodos de extensão e como construir Regex. Se você estiver interessado em aprender mais sobre os métodos de extensão no Dart, verifique aqui e aqui está o que você precisa saber sobre como construir seu próprio Regex .

Você notará que nossa extensão de string contém cinco métodos:

  • isValidEmail
  • isValidName
  • isValidPassword
  • éNotNull
  • isValidPhone

Todos os métodos Regex acima pegam a string e verificam se ela corresponde ao padrão Regex e, em seguida, retorna true ou false se não corresponder. Agora, tudo o que precisamos fazer é importar esse arquivo para qualquer um dos nossos arquivos, precisamos usar os métodos de extensão.

De volta ao nosso widget FormPage (). Esta é a aparência de nosso widget.

 import'package: Flutter/material.dart';
import'package: form_validation_demo/core/extensions/extensions.dart';
import'package: form_validation_demo/form/success.dart'; class FormPage extends StatefulWidget { @sobrepor _FormPageState createState ()=> _FormPageState ();
} class _FormPageState extends State  { //Esta chave será usada para identificar o estado do formulário. final _formKey=GlobalKey  (); @sobrepor Construção de widget (contexto BuildContext) { return Scaffold ( corpo: SafeArea ( criança: Container ( preenchimento: EdgeInsets.all (20), filho: Formulário ( chave: _formKey, filho: coluna ( crianças: [ _nameTextField (), _emailTextField (), _phoneTextField (), _passwordTextField (), _botão de envio() ], ), ), ), )); } Widget _emailTFTextField () { return TextFormField ( decoração: InputDecoration (hintText:'Email'), validador: (v) { if (v.isValidEmail) { return null; } senão { return'Por favor, insira um email válido'; } }, ); } Widget _passwordTextField () { return TextFormField ( obscureText: true, decoração: InputDecoration (hintText:'Password'), validador: (v) { if (v.isValidPassword) { return null; } senão { return'A senha deve conter maiúscula, minúscula, dígito numérico e caractere especial'; } }, ); } Widget _nameTextField () { return TextFormField ( decoração: InputDecoration (hintText:'Name'), validador: (v) { if (v.isValidName) { return null; } senão { return'Por favor, insira um nome válido'; } }, ); } Widget _phoneTextField () { return TextFormField ( decoração: InputDecoration (hintText:'Phone'), validador: (v) { if (v.isValidPhone) { return null; } senão { retornar'O número do telefone deve ter até 11 dígitos'; } }, ); } Widget _submitButton () { recipiente de retorno ( preenchimento: EdgeInsets.all (20), filho: ElevatedButton ( filho: Texto ('Enviar'), onPressed: () { if (_formKey.currentState.validate ()) { Navigator.push ( contexto, MaterialPageRoute (construtor: (_)=> SuccessPage ())); } }, ), ); }
}

Nossa árvore de widgets é composta de: A Scaffold=> SafeArea=> Container=> Form=> Column.

Criamos um formKey que será adicionado ao nosso widget de formulário para identificar o estado do nosso formulário, que é criado por padrão no Flutter ao usar um formulário.

Dentro de nossa coluna, temos cinco funções que retornam um widget. Os primeiros quatro são nossos campos, enquanto o último é o botão de envio.

Vamos dar uma olhada cuidadosa em uma das funções em nossa coluna.

 Widget _emailTextField () { return TextFormField ( decoração: InputDecoration (hintText:'Email'), validador: (v) { if (v.isValidEmail) { return null; } senão { return'Por favor, insira um email válido'; } }, ); }

emailTextField simplesmente retorna um TextFormField . A parte mais importante disso é o campo validator .

O campo validator recebe a entrada do usuário e verifica se ela satisfaz nossa condição Regex. Em caso afirmativo, o campo retorna null . Caso contrário, ele retornará uma string, que será a mensagem de erro exibida em nosso campo de texto.

Simplesmente repetimos isso para nossos outros campos de entrada e usamos os métodos de extensão correspondentes de nossa classe de extensão.

A forma como acionamos a validação nesta página é usando a variável-chave do formulário que criamos para nos dar acesso ao estado do nosso formulário.

 Widget _submitButton () { recipiente de retorno ( preenchimento: EdgeInsets.all (20), filho: ElevatedButton ( filho: Texto ('Enviar'), onPressed: () { if (_formKey.currentState.validate ()) { Navigator.push ( contexto, MaterialPageRoute (construtor: (_)=> SuccessPage ())); } }, ), ); }

Portanto, sempre que um usuário clica no botão, verificamos _formKey.currentState.validate () ,
em seguida, realizamos uma ação que, no nosso caso, seria simplesmente navegar para uma nova tela.

Sua página de sucesso pode ser qualquer coisa ou qualquer tela para a qual você deseja levar o usuário após concluir a validação do campo e usar os dados inseridos pelo usuário.

Validação de formulário usando provedor

Usar Provider é outra maneira de validar campos em Flutter. Essa técnica é usada principalmente quando preciso realizar algumas tarefas na entrada do usuário sem desordenar as classes de IU com códigos. É por isso que movemos a lógica para nossa classe Provider .

Usaremos o pacote Provider e o adicionaremos ao nosso arquivo pubspec.yaml :

 # O seguinte adiciona a fonte Cupertino Icons ao seu aplicativo.
# Use com a classe CupertinoIcons para ícones de estilo iOS.
cupertino_icons: ^ 1.0.0
fornecedor:

Nosso arquivo pubspec.yaml agora deve ser semelhante ao anterior, e podemos prosseguir para executar o Flutter pub get para baixar as dependências necessárias.

Então, podemos criar um novo arquivo chamado form_provider e criar uma classe dentro dele que estende, ChangeNotifier . A classe ChangeNotifier fornece métodos que nos permitem ouvir as alterações em objetos que assinamos usando o ChangeNotifier .

É por isso que um dos métodos mais importantes fornecidos por esta classe é notifylisteners () .

Este método instrui nossos ouvintes a obter os valores mais recentes dos objetos ou variáveis ​​que eles assinam.

Antes de passarmos para a criação de nossa classe provedor , vamos criar um modelo que terá duas variáveis, uma string error e outra string que chamaremos de valor por enquanto.

 class ValidationModel { Valor da string; Erro de string; ValidationModel (this.value, this.error);
}

Em nossa classe Provider , vamos criar quatro campos em nosso ValidationModel para as entradas que recebemos do usuário: e-mail, senha, telefone e nome do usuário. Esses campos serão privados, portanto, vamos expô-los usando getters.

 class FormProvider extends ChangeNotifier { ValidationModel _email=ValidationModel (nulo, nulo); ValidationModel _password=ValidationModel (nulo, nulo); ValidationModel _phone=ValidationModel (nulo, nulo); ValidationModel _name=ValidationModel (nulo, nulo); ValidationModel get email=> _email; ValidationModel obter senha=> _password; ValidationModel get phone=> _phone; ValidationModel get name=> _name;
}

Além disso, criamos métodos que obterão a entrada dos campos de texto e os validarão em relação às nossas condições.

Se atenderem aos nossos requisitos, retornamos null para a mensagem de erro ValidationModel e, se a entrada do usuário não atender aos nossos critérios, retornamos a mensagem de erro com a mensagem que desejamos exibir em nosso tela.

Finalmente, chamaremos notifylisteners e passaremos o getter para os campos de mensagem de erro em cada um dos nossos campos de texto.

Esses métodos serão parecidos com este:

 String validateEmail (String val) { if (val.isValidEmail) { _email=ValidationModel (val, null); } senão { _email=ValidationModel (null,'Digite um e-mail válido'); } notificarListeners ();
} String validatePassword (String val) { if (val.isValidPassword) { _password=ValidationModel (val, null); } senão { _password=ValidationModel (nulo, 'A senha deve conter maiúscula, minúscula, dígito numérico e caractere especial'); } notificarListeners ();
} String validateName (String val) { if (val.isValidName) { _name=ValidationModel (val, null); } senão { _name=ValidationModel (null,'Digite um nome válido'); } notificarListeners ();
} String validatePhone (String val) { if (val.isValidPhone) { _phone=ValidationModel (val, null); } senão { _phone=ValidationModel (null,'Número de telefone deve ter até 11 dígitos'); } notificarListeners ();
} bool get validate { if (_email.value.isNotNull && _password.value.isNotNull && _phone.value.isNotNull && _name.value.isNotNull) { return true; } senão { retorna falso; }
}

Agora, em nossa classe Provider , temos uma função getter chamada validate que retornará true se todas as nossas condições de validação forem atendidas.

Em nossa classe de IU, substituiremos o código anterior que tínhamos por algo assim:

 import'package: Flutter/material.dart';
import'package: form_validation_demo/form/success.dart';
import'package: form_validation_demo/provider_validation/form_provider.dart';
import'package: provider/provider.dart'; class ProviderFormPage extends StatefulWidget { @sobrepor _ProviderFormPageState createState ()=> _ProviderFormPageState ();
} class _ProviderFormPageState extends State  { var _formProvider; @sobrepor Construção de widget (contexto BuildContext) { _formProvider=Provider.of  (contexto); return SafeArea ( criança: Scaffold ( corpo: Container ( preenchimento: EdgeInsets.all (20), filho: Formulário ( filho: coluna ( crianças: [ TextFormField ( onChanged: (String val) { _formProvider.validateName (val); }, keyboardType: TextInputType.name, decoração: InputDecoration ( errorText: _formProvider.name.error, hintText:"Digite seu nome", ), ), TextFormField ( onChanged: (String val) { _formProvider.validateEmail (val); }, keyboardType: TextInputType.emailAddress, decoração: InputDecoration ( errorText: _formProvider.email.error, hintText:"Digite seu e-mail", ), ), TextFormField ( onChanged: (String val) { _formProvider.validatePhone (val); }, keyboardType: TextInputType.phone, decoração: InputDecoration ( errorText: _formProvider.phone.error, hintText:"Digite seu número de telefone", ), ), TextFormField ( onChanged: (String val) { _formProvider.validatePassword (val); }, obscureText: true, decoração: InputDecoration ( errorText: _formProvider.password.error, hintText:"Digite sua senha", ), ), Consumidor  ( construtor: (contexto, modelo, filho)=> Contêiner ( preenchimento: EdgeInsets.all (20), filho: ElevatedButton ( filho: Texto ('Enviar'), onPressed: (model.validate) ? () { Navigator.push ( contexto, MaterialPageRoute ( construtor: (_)=> SuccessPage ())); } : nulo, ), ), ) ], ), ), ), ), ); }
}

Por último, antes de usar qualquer Provider , precisamos registrá-lo em uma posição mais alta em nossa árvore de widgets.

Vamos fazer isso em nosso arquivo main.dart .

 void main () { runApp (ChangeNotifierProvider  (
criar: (_)=> FormProvider (), filho: MyApp ()));
}

Agora podemos prosseguir para executar nosso aplicativo e ver que temos resultados semelhantes à abordagem anterior. A principal razão para usar a segunda abordagem-mesmo que pareça mais trabalho em termos de linhas de códigos-é se você se encontrar em um cenário em que adoraria manter seu código de IU limpo e organizado e sem todos os dados manipulações em seu aplicativo.

Outra vantagem de usar a abordagem do Provedor é que ela valida a entrada do usuário enquanto o usuário interage com os campos de texto. Isso significa que o usuário não espera para clicar no botão enviar para saber se sua entrada é válida ou não.

Além dessa abordagem de validação de formulários na IU, que não é totalmente nova, ainda existem muitas outras maneiras de validar um formulário. A biblioteca de blocos também fornece um pacote Flutter para validar campos-é chamado de form_bloc . Você pode verificar a documentação aqui . Muito obrigado por ler!

A postagem Introdução à validação de formulário no Flutter apareceu primeiro no LogRocket Blog .

Source link