Cuando crea varios formularios (por ejemplo: registro o inicio de sesión) en Flutter, no se molesta en personalizar los componentes, porque puede cambiar cualquier campo de formulario para que se adapte a su estilo.
Además de la personalización, Flutter proporciona funciones de validación de campos de formulario y manejo de errores.
Y hoy trataremos de tratar este tema con un pequeño ejemplo.
¡Bueno, vamos!
Nuestro plan
Parte 1 - introducción al desarrollo, primer apéndice, concepto de estado;
Parte 2 : archivo pubspec.yaml y uso de flutter en la línea de comandos;
Parte 3 - BottomNavigationBar y Navigator;
Parte 4 - MVC. Usaremos este patrón en particular como uno de los más simples;
Parte 5 - paquete http. Creación de la clase Repository, primeras solicitudes, listado de publicaciones;
Parte 6 (artículo actual): trabajar con formularios, campos de texto y crear una publicación.
Parte 7: trabajar con imágenes, mostrar imágenes en forma de cuadrícula, recibir imágenes de la red, agregar las suyas a la aplicación;
Parte 8: creación de su propio tema, agregando fuentes y animaciones personalizadas;
Parte 9: un poco sobre las pruebas;
Creación de formularios: agregar una publicación
Primero, HomePage
agreguemos un botón a nuestra página mediante el cual agregaremos una nueva publicación:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Post List Page"),
),
body: _buildContent(),
// FloatingActionButton
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
},
),
);
}
A continuación, creemos una nueva página en el archivo post_add_page.dart
:
import 'package:flutter/material.dart';
class PostDetailPage extends StatefulWidget {
@override
_PostDetailPageState createState() => _PostDetailPageState();
}
class _PostDetailPageState extends State<PostDetailPage> {
// TextEditingController'
final TextEditingController titleController = TextEditingController();
final TextEditingController contentController = TextEditingController();
// _formKey
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Post Add Page"),
actions: [
// AppBar
IconButton(
icon: Icon(Icons.check),
onPressed: () {
//
if (_formKey.currentState!.validate()) {
// c
}
},
)
],
),
body: Padding(
padding: EdgeInsets.all(15),
child: _buildContent(),
),
);
}
Widget _buildContent() {
//
return Form(
key: _formKey,
//
child: Column(
children: [
//
TextFormField(
// ,
// (hint)
decoration: InputDecoration(
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.face),
hintText: ""
),
// TextEditingController
controller: titleController,
// validator - ,
// null
//
validator: (value) {
// 2
if (value == null || value.isEmpty) {
return " ";
}
if (value.length < 3) {
return " 3 ";
}
return null;
},
),
//
SizedBox(height: 10),
// Expanded ,
//
Expanded(
child: TextFormField(
// maxLines: null expands: true
//
maxLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "",
),
// TextEditingController
controller: contentController,
//
validator: (value) {
if (value == null || value.isEmpty) {
return " ";
}
return null;
},
),
)
],
),
);
}
}
No olvide agregar una transición a la página del formulario:
floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (context) => PostDetailPage() )); }, ),
Ejecute y haga clic en el botón:
! .
. , .
100%- Flutter Dart :
Flutter 2.0.6
Dart SDK version: 2.12.3
null safety. , .
null safety. :
// ! , 100%
// currentState null
_formKey.currentState!.validate()
null safety Dart , .
POST .
POST
POST, , HTTP .
Post
:
class Post {
// private
//
final int? _userId;
final int? _id;
final String? _title;
final String? _body;
// getters
//
int? get userId => _userId;
int? get id => _id;
String? get title => _title;
String? get body => _body;
//
Post(this._userId, this._id, this._title, this._body);
// toJson() Post JSON
String toJson() {
return json.encode({
"title": _title,
"content": _body
});
}
// Dart
// Post.fromJson(json) -
//
// , dynamic
// : String, int, double ..
Post.fromJson(Map<String, dynamic> json) :
this._userId = json["userId"],
this._id = json["id"],
this._title = json["title"],
this._body = json["body"];
}
//
abstract class PostAdd {}
//
class PostAddSuccess extends PostAdd {}
//
class PostAddFailure extends PostAdd {}
Repository
:
//
Future<PostAdd> addPost(Post post) async {
final url = Uri.parse("$SERVER/posts");
// POST ,
// JSON
final response = await http.post(url, body: post.toJson());
//
if (response.statusCode == 201) {
// ,
return PostAddSuccess();
} else {
//
return PostAddFailure();
}
}
PostController
:
//
// addPost callback,
//
void addPost(Post post, void Function(PostAdd) callback) async {
try {
final result = await repo.addPost(post);
//
callback(result);
} catch (error) {
//
callback(PostAddFailure());
}
}
PostAddPage
:
class PostDetailPage extends StatefulWidget {
@override
_PostDetailPageState createState() => _PostDetailPageState();
}
// StateMVC
class _PostDetailPageState extends StateMVC {
// _controller null
PostController? _controller;
// PostController
_PostDetailPageState() : super(PostController()) {
_controller = controller as PostController;
}
// TextEditingController'
final TextEditingController titleController = TextEditingController();
final TextEditingController contentController = TextEditingController();
// _formKey
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Post Add Page"),
actions: [
// AppBar
IconButton(
icon: Icon(Icons.check),
onPressed: () {
//
if (_formKey.currentState!.validate()) {
//
// TextEditingController'
final post = Post(
-1, -1, titleController.text, contentController.text
);
//
_controller!.addPost(post, (status) {
if (status is PostAddSuccess) {
//
//
//
Navigator.pop(context, status);
} else {
//
// SnackBar -
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(" "))
);
}
});
}
},
)
],
),
body: Padding(
padding: EdgeInsets.all(15),
child: _buildContent(),
),
);
}
Widget _buildContent() {
//
return Form(
key: _formKey,
//
child: Column(
children: [
//
TextFormField(
// ,
// (hint)
decoration: InputDecoration(
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.face),
hintText: ""
),
// TextEditingController
controller: titleController,
// validator - ,
// null
//
validator: (value) {
// 2
if (value == null || value.isEmpty) {
return " ";
}
if (value.length < 3) {
return " 3 ";
}
return null;
},
),
//
SizedBox(height: 10),
// Expanded ,
//
Expanded(
child: TextFormField(
// maxLines: null expands: true
//
maxLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "",
),
// TextEditingController
controller: contentController,
//
validator: (value) {
if (value == null || value.isEmpty) {
return " ";
}
return null;
},
),
)
],
),
);
}
}
:
,
, .
, PostListPage
:
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
// then Future
//
Navigator.push(context, MaterialPageRoute(
builder: (context) => PostDetailPage()
)).then((value) {
if (value is PostAddSuccess) {
// SnackBar -
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(" "))
);
}
});
},
),
:
Espero haberte convencido de que trabajar con formularios en Flutter es muy fácil y casi no requiere esfuerzo.
La mayor parte del código realiza una solicitud POST al servidor y maneja errores.
Enlaces útiles
Buen código para todos)