Kodokon kodokon.com

النماذج: TextField والمتحكِّمات والتحقّق

تحكّم في حقول الإدخال باستخدام TextEditingController وتحقّق من كل إدخال دفعة واحدة بفضل Form وTextFormField.

9 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

إن حقل الإدخال بلا متحكِّم صندوق أسود. يمنحك TextEditingController زمام التحكّم: اقرأ controller.text في أيّ لحظة، واملأ الحقل مسبقًا، وامسحه بعد الإرسال، أو أنصت إلى كل ضغطة مفتاح باستخدام addListener. يُنشأ المتحكِّم في State، لا في build أبدًا - وإلا فسيُعاد إنشاؤه عند كل إعادة بناء.

DART
import 'package:flutter/material.dart';

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

  @override
  State<NicknameField> createState() =>
      _NicknameFieldState();
}

class _NicknameFieldState extends State<NicknameField> {
  final _controller = TextEditingController();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: _controller,
      decoration: const InputDecoration(
        labelText: 'Nickname',
        border: OutlineInputBorder(),
      ),
      onSubmitted: (value) => debugPrint(value),
    );
  }
}
يعيش المتحكِّم في State ويموت في dispose().

حالما تحتوي شاشة على عدة حقول للتحقّق منها، اعتمد الثلاثي Form وGlobalKey<FormState> وTextFormField. يصف كل حقل قاعدته في validator: تُرجِع الدالة رسالة خطأ، أو null إذا كان كل شيء على ما يرام. ويُطلق استدعاء validate() على المفتاح كل دوال التحقّق دفعة واحدة.

DART
import 'package:flutter/material.dart';

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

  @override
  State<SignUpForm> createState() => _SignUpFormState();
}

class _SignUpFormState extends State<SignUpForm> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();

  @override
  void dispose() {
    _emailController.dispose();
    super.dispose();
  }

  void _submit() {
    if (_formKey.currentState!.validate()) {
      debugPrint('Email: ${_emailController.text}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          TextFormField(
            controller: _emailController,
            keyboardType: TextInputType.emailAddress,
            decoration: const InputDecoration(
              labelText: 'Email',
            ),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Required field';
              }
              if (!value.contains('@')) {
                return 'Invalid address';
              }
              return null;
            },
          ),
          const SizedBox(height: 16),
          FilledButton(
            onPressed: _submit,
            child: const Text('Create account'),
          ),
        ],
      ),
    );
  }
}
يُطلق validate() كل دالة تحقّق في النموذج.

عند النقر على الزر، يُنفِّذ validate() كل validator: تظهر الرسائل المُرجَعة باللون الأحمر تحت الحقول المعنية، وتُرجِع الدالة false إذا كان حقل واحد على الأقل غير صالح. لذا يظل منطق الإرسال خلف if واحد - ويستحيل إرسال بيانات غير صالحة.

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. ما وظيفة TextEditingController؟
    • لرسم حدود الحقل
    • لقراءة نص الحقل وتعديله، والإنصات إلى تغيّراته
    • للتحقّق تلقائيًا من عناوين البريد الإلكتروني
    • لإغلاق لوحة المفاتيح
  2. ماذا يجب أن تُرجِع دالة validator عندما تكون القيمة صالحة؟
    • true
    • سلسلة فارغة
    • null
    • القيمة نفسها
  3. لماذا تستدعي _controller.dispose() في دالة dispose() الخاصة بـ State؟
    • لمسح الحقل على الشاشة
    • لتحرير الموارد وتجنّب تسريبات الذاكرة
    • لإرسال النموذج