Conceptos básicos de Flutter para principiantes (Parte VI)

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;
              },
            ),
          )
        ],
      ),
    );
  }

}
      
      



:









  1. ,





  2. , .





, 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("   "))
        );
      }
    });
  },
),
      
      



:





JSONPlaceholder .





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





  • Código fuente en Github





  • Construya un formulario con validación (EN)





  • Dardo nulo seguridad





Buen código para todos)








All Articles