I have a List of items that I retrieve from a database with http.get method. I need to create a validator that only allow users to submit if the value typed is equal to at least one of the values of the list.
Example: The list is: [{name: Peter, email: [email protected]}{name: Mathew, email: [email protected]}]. Then I have two textFormFields, one for NAME and another for EMAIL. So if the NAME and EMAIL the user types match any of the items of the list, than user can submit. I created the http.get method and I created the TextFormfields, but I cannot figure how to create the validator.
Here is the Formulary code:
// ignore_for_file: no_leading_underscores_for_local_identifiers, prefer_typing_uninitialized_variables
import 'dart:convert';
import 'package:apetit_project/components/teste_app_users_item.dart';
import 'package:apetit_project/models/app_user.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../models/auth_form_data.dart';
import 'package:http/http.dart' as http;
import '../models/user_data.dart';
class AuthForm extends StatefulWidget {
final void Function(AuthFormData) onSubmit;
const AuthForm({
Key? key,
required this.onSubmit,
}) : super(key: key);
@override
State<AuthForm> createState() => _AuthFormState();
}
class _AuthFormState extends State<AuthForm> {
TextEditingController _emailController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
final _formData = AuthFormData();
List<dynamic> _teste = [];
List<dynamic> get teste => [..._teste];
final _url = 'URL';
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
bool isLogin = true;
late String title;
late String actionButton;
late String toggleButton;
void _submit() {
final isValid = _formKey.currentState?.validate() ?? false;
if (!isValid) return;
widget.onSubmit(_formData);
}
Future<void> _loadUsers() async {
final response = await http.get(
Uri.parse('http://172.16.30.120:8080/ords/apiteste/integrafoods/users'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
);
if (response.body == 'null') return;
final data = jsonDecode(response.body)['items'] as List?;
if (data != null) {
// _teste = data;
_teste = data.map((e) => MyItem.fromMap(e)).toList();
print(data);
}
// print(_teste.toList());
}
@override
_initState() {
_loadUsers();
super.initState();
}
@override
Widget build(BuildContext context) {
// print(_teste);
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/Login.png'),
fit: BoxFit.cover,
alignment: Alignment.center,
),
),
child: Container(
margin: const EdgeInsets.only(bottom: 20),
child: Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (_formData.isSignup)
TextFormField(
key: const ValueKey('Nome'),
initialValue: _formData.name,
onChanged: (name) => _formData.name = name,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
prefixIcon: Padding(
padding: const EdgeInsets.only(left: 18, right: 18),
child: Image.asset(
'assets/images/password_icon.png',
scale: 6,
color: Colors.black,
),
),
labelText: 'Nome',
labelStyle: const TextStyle(color: Colors.black),
),
keyboardType: TextInputType.emailAddress,
),
const SizedBox(
height: 4,
),
TextFormField(
// controller: _emailController,
key: const ValueKey('Email'),
initialValue: _formData.email,
onChanged: (email) => _formData.email = email,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
prefixIcon: Image.asset(
'assets/images/email_icon.png',
scale: 6,
color: Colors.black,
),
labelText: 'Email',
labelStyle: const TextStyle(color: Colors.black),
),
validator: (_email) {
final email = _email ?? '';
if (!email.contains('@')) {
return 'E-mail informado não é válido.';
}
return null;
},
keyboardType: TextInputType.emailAddress,
),
const SizedBox(
height: 4,
),
TextFormField(
// controller: _passwordController,
key: const ValueKey('password'),
initialValue: _formData.password,
onChanged: (password) => _formData.password = password,
style: const TextStyle(color: Colors.black),
obscureText: true,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(30)),
prefixIcon: Padding(
padding: const EdgeInsets.only(left: 18, right: 18),
child: Image.asset(
'assets/images/password_icon.png',
scale: 6,
color: Colors.black,
),
),
labelText: 'Senha',
labelStyle: const TextStyle(color: Colors.black)),
validator: (_password) {
final password = _password ?? '';
if (password.length < 6) {
return 'Senha deve ter no mínimo 6 caracteres';
}
return null;
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: _loadUsers,
child: Text('teste'),
),
// Expanded(
// child: ListView.builder(
// itemBuilder: (ctx, index) {
// return Card(
// child: ClipRRect(child: MyItemItem(_teste[index])));
// },
// itemCount: _teste.length,
// ),
// ),
SizedBox(
width: double.infinity,
child: ElevatedButton(
// onPressed: _signInUser,
onPressed: _submit,
style: ButtonStyle(
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
)),
padding:
MaterialStateProperty.all(const EdgeInsets.all(15)),
backgroundColor: MaterialStateProperty.all(
Theme.of(context).colorScheme.secondary),
),
child: Text(
_formData.isLogin ? 'Entrar' : 'Cadastrar',
style: const TextStyle(
color: Colors.black,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold),
),
),
),
TextButton(
onPressed: () {
setState(() {
_formData.toggleAuthMode();
});
},
child: Text(
_formData.isLogin
? 'Criar uma nova conta?'
: 'Já possui conta?',
),
),
],
),
),
),
),
),
);
}
// Future _signInUser() async {
// await FirebaseAuth.instance.signInWithEmailAndPassword(
// email: _emailController.text,
// password: _passwordController.text,
// );
// }
}
and here is the "My item" class
import 'dart:convert';
class MyItem {
final int id;
final String email;
final String? cpf;
MyItem({
required this.id,
required this.email,
required this.cpf,
});
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
result.addAll({'sequencia': id});
if (email != null) {
result.addAll({'email': email});
}
if (cpf != null) {
result.addAll({'cpf': cpf});
}
return result;
}
factory MyItem.fromMap(Map<String, dynamic> map) {
return MyItem(
id: int.tryParse(map['sequencia'].toString()) ?? 0,
email: map['email'],
cpf: map['cpf'],
);
}
String toJson() => json.encode(toMap());
factory MyItem.fromJson(String source) => MyItem.fromMap(json.decode(source));
}
How can I fix it?
CodePudding user response:
The following should do the trick. Do the same for name
and you're good to go.
validator: (_email) {
final email = _email ?? '';
if (!email.contains('@')) {
return 'E-mail informado não é válido.';
}
if (!_teste.any((item) => item.email == email)) { // <- Here
return 'E-mail já cadastrado.'; // <- Here
}
return null;
},