aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

Flutter Form: validate dữ liệu trước khi gọi save

Suong Nguyen by Suong Nguyen
25/10/2026
in Flutter
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Một form có TextField và nút gửi chưa tự có chính sách dữ liệu hợp lệ. Nếu phần hiển thị lỗi, lấy giá trị và xử lý nút bấm nằm rải rác, bạn dễ lưu chuỗi trắng hoặc tưởng rằng save() đã tự kiểm tra mọi điều kiện.

Bài này tạo form kiểm tra tên dự án bằng Form và TextFormField. Tài liệu Flutter được đối chiếu ngày 25/10/2026; cookbook hiện ghi phạm vi Flutter 3.47. Ví dụ được rà theo API nhưng chưa build hoặc chạy widget test trong lượt biên tập. Nó chỉ kiểm tra dữ liệu local, chưa tạo dự án trên server hay lưu database.

1. Ba trách nhiệm cần tách rõ

Cookbook validation của Flutter dùng Form để nhóm các field và GlobalKey để truy cập FormState. Validator trả chuỗi lỗi khi chưa hợp lệ, trả null khi hợp lệ. GlobalKey nên được tạo một lần ở State thay vì tạo lại trong mỗi lần build.

validate() chạy các validator và cho biết form hợp lệ hay không. FormState.save gọi lưu trên các field con; callback onSaved nhận giá trị của field. Trong luồng dưới đây, chúng ta chỉ gọi save sau khi validate thành công.

2. Ví dụ một form tự đủ

Đặt vào lib/main.dart của một dự án Flutter thử. Chỉ có một field bắt buộc để bạn tập trung vào đường đi của dữ liệu, không phải vào nhiều quy tắc nghiệp vụ cùng lúc.

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: ProjectFormPage()));

class ProjectFormPage extends StatefulWidget {
  const ProjectFormPage({super.key});

  @override
  State<ProjectFormPage> createState() => _ProjectFormPageState();
}

class _ProjectFormPageState extends State<ProjectFormPage> {
  final _formKey = GlobalKey<FormState>();
  String _projectName = '';

  String? _validateName(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'Bạn cần nhập tên dự án';
    }
    return null;
  }

  void _checkInput() {
    final form = _formKey.currentState;
    if (form == null || !form.validate()) return;
    form.save();
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Đã kiểm tra: $_projectName')),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Kiểm tra tên dự án')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              TextFormField(
                decoration: const InputDecoration(labelText: 'Tên dự án'),
                validator: _validateName,
                autovalidateMode: AutovalidateMode.onUserInteraction,
                onSaved: (value) => _projectName = (value ?? '').trim(),
              ),
              const SizedBox(height: 16),
              FilledButton(
                onPressed: _checkInput,
                child: const Text('Kiểm tra dữ liệu'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Thông báo thành công dùng từ “đã kiểm tra” vì ví dụ không lưu dữ liệu bền vững. Đặt thông báo đúng với việc thực sự xảy ra giúp bạn không nhầm một prototype local với một luồng tạo dự án hoàn chỉnh.

3. Chuẩn hóa giá trị một cách nhất quán

Validator dùng trim để coi chuỗi chỉ có khoảng trắng là chưa có tên. OnSaved cũng trim trước khi ghi vào biến, nên điều kiện kiểm tra và giá trị nhận được thống nhất ở điểm này.

Đây là quyết định dành cho tên dự án trong ví dụ. Không sao chép trim cho mọi loại dữ liệu; một số trường có thể cần giữ nguyên khoảng trắng. Nếu có giới hạn độ dài, hãy định nghĩa cách đếm ký tự và kiểm tra Unicode phù hợp thay vì thêm một con số tùy ý vào validator.

Validator nên mô tả điều kiện của field và trả kết quả. Đừng gọi request mạng, thay route hoặc ghi dữ liệu trong validator chỉ vì nó được chạy khi bấm nút. Những hành động đó cần một luồng xử lý riêng có trạng thái chờ và lỗi rõ ràng.

4. Chọn thời điểm hiện lỗi

Trong ví dụ, field dùng AutovalidateMode.onUserInteraction. Người dùng có thể thấy phản hồi sau khi tương tác; nút kiểm tra vẫn gọi validate để xử lý trường hợp chưa nhập gì rồi bấm ngay. Nếu sản phẩm muốn chỉ hiện lỗi sau lần submit đầu, hãy thiết kế chính sách đó riêng và thử lại toàn bộ luồng.

Với nhiều field, ghi thông báo chỉ ra việc cần sửa. “Dữ liệu sai” thường không đủ giúp người dùng biết phải làm gì. Khi có lỗi từ server, phân biệt lỗi field với lỗi chung và tránh xóa nội dung người dùng đã nhập chỉ vì một request thất bại.

Kiểm tra kết quả

Trên emulator hoặc thiết bị, thử chuỗi rỗng, chỉ có dấu cách, tên tiếng Việt bình thường và tên có khoảng trắng hai đầu. Bấm nút trước khi nhập rồi sửa field. Xác nhận lỗi biến mất theo chính sách đã chọn và thông báo sau kiểm tra dùng giá trị đã trim.

Tiếp tục thử khi bàn phím mở và cỡ chữ hệ thống tăng. ScrollView giúp nội dung có đường cuộn, nhưng không tự chứng minh mọi thiết bị đều bố trí tốt; vẫn phải kiểm tra nút và thông báo lỗi không bị che hoặc cắt.

Lỗi thường gặp

Nếu currentState là null, kiểm tra key có gắn đúng Form và callback có chạy khi Form còn trong cây không. Nếu validator không được gọi, kiểm tra bạn dùng TextFormField trong Form thay vì chỉ có TextField. Nếu onSaved chưa chạy, xem nhánh validate có trả false hoặc code đã return trước đó không.

Nếu rebuild làm form giống như mới tạo, tìm GlobalKey được khởi tạo trong build. Khi dữ liệu đã hợp lệ nhưng cần lưu thật, hãy bổ sung luồng lưu có xử lý lỗi theo yêu cầu sản phẩm; không đổi tên callback save thành bằng chứng rằng database đã được cập nhật.

Kết luận

Giữ key ổn định, để validator chỉ ra điều kiện chưa đạt và gọi save có chủ đích sau validate. Một form nhỏ với kỳ vọng rõ ràng giúp bạn phát triển luồng nhập liệu tiếp theo mà không trộn kiểm tra giao diện với việc lưu dữ liệu.

Nguồn tham khảo

  • Flutter: build a form with validation
  • Flutter: FormState.save
  • Flutter: FormField.onSaved

Tags: FlutterFormValidation
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

Flutter ValueKey: giữ state đi cùng dữ liệu khi đảo thứ tự danh sách

by Suong Nguyen
26/10/2026
0

Dựng hai hàng có bộ đếm riêng để hiểu key ổn định, vị trí widget và lý do UniqueKey mới mỗi lần build có thể làm mất state.

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

TextEditingController trong Flutter: giữ nội dung và con trỏ đúng vòng đời

by Suong Nguyen
24/10/2026
0

Tổ chức TextEditingController trong State, cập nhật text và selection cùng lúc, tránh reset nội dung khi widget rebuild.

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

ValueNotifier trong Flutter: cập nhật list để giao diện nhận đúng thay đổi

by Suong Nguyen
23/10/2026
0

Hiểu cách ValueNotifier dùng phép so sánh bằng, cập nhật list bằng giá trị mới và quản lý vòng đời notifier rõ ràng.

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

Tìm kiếm Flutter: debounce và chặn response cũ ghi đè kết quả mới

by Suong Nguyen
22/10/2026
0

Kết hợp Timer, mã phiên truy vấn và kiểm tra mounted để màn hình tìm kiếm không hiển thị nhầm kết quả khi mạng trả về lệch thứ...

Next Post
Minh họa các khái niệm AI, mạng nơ-ron và lập trình trên máy tính

Đánh giá truy hồi RAG bằng Recall@k và MRR trước khi sửa prompt

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native Image: cover và contain khác nhau trong cùng một khung ảnh
  • JavaScript sort: vì sao số 10 đứng trước 2 và mảng gốc bị đổi?
  • Android plurals: vì sao getQuantityString cần truyền count hai lần?

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply