FlutterFlutter · Chapterبەش 8 · Lectureوانە 8.3

Text Fields and Formsخانەکانی دەق و فۆرمەکان

TextField and InputDecoration (label, hint, helper, icons, border, error), the right keyboard and obscureText, reading the text with onChanged or a TextEditingController (created once, disposed), and Form + TextFormField + validator + GlobalKey<FormState> with autovalidateMode — ending in a complete login form.

TextField و InputDecoration (، ڕێنمایی، یارمەتی، ، ، )، گونجاو و obscureText، خوێندنەوەی دەق بە onChanged یان TextEditingController (یەک جار دروست دەکرێت، dispose دەکرێت) و ⁦Form + TextFormField + validator + GlobalKey<FormState>⁩ لەگەڵ autovalidateMode — کە بە تەواوی کۆتایی دێت.

19 min read17 خولەک خوێندنەوە · 15 stepsهەنگاو

What you will learnچی فێر دەبیت

  • Build a TextField and decorate it with InputDecoration (label, hint, icons, border).
  • Choose the keyboard and hide passwords with obscureText.
  • Read text with onChanged or a TextEditingController, and dispose the controller.
  • Validate a Form with TextFormField validators and a GlobalKey<FormState>.
  • Build a login form and explain why the server must validate again.
  • TextFieldـێک دروست بکەیت و بە InputDecoration (، ڕێنمایی، ، ) بیڕازێنیتەوە.
  • هەڵبژێریت و بە obscureText بشاریتەوە.
  • دەق بە onChanged یان TextEditingController بخوێنیتەوە و controllerـەکە dispose بکەیت.
  • Formـێک بە validatorـی TextFormField و ⁦GlobalKey<FormState>⁩ بپشکنیت.
  • دروست بکەیت و ڕوون بکەیتەوە بۆچی دەبێت دووبارە بپشکنێتەوە.

Letting the user typeڕێگەدان بە بەکارهێنەر بۆ نووسین

The course defines a text field (also called a text box) as an input element which holds alphanumeric data: letters and numbers such as a name, a password or an address. In Flutter the basic widget is TextField. Its sibling TextFormField is the same field plus validation, made to live inside a Form.

وانەکە (کە پێی دەوترێت یش) وا پێناسە دەکات: توخمێکی کە پیت و ژمارە هەڵدەگرێت: وەک ناو، یان ناونیشان. لە Flutterـدا بنەڕەتی TextFieldـە. هاوشێوەکەی TextFormField هەمان خانەیە لەگەڵ ، کە بۆ ژیان لە ناو Formـێکدا دروست کراوە.

A form at the post officeفۆرمێک لە پۆستەخانە

Think of the paper form at a post office: each box has a printed label (Name, Phone), sometimes a small grey example inside (0750…), and the clerk checks every box before accepting the form. A TextField is one box; InputDecoration is everything printed around it; a Form with validators is the clerk.

بیر لە فۆرمێکی کاغەزی لە پۆستەخانەدا بکەرەوە: هەر خانەیەک چاپکراوی هەیە (Name، Phone)، هەندێک جار نموونەیەکی خۆڵەمێشیی بچووک لە ناویدا (⁦0750⁩…). فەرمانبەرەکەش پێش وەرگرتنی فۆرمەکە هەموو خانەیەک دەپشکنێت. TextField یەک خانەیە؛ InputDecoration هەموو ئەو شتانەیە کە بە دەوریدا چاپ کراون؛ Formـێک بە validatorـەکانییەوە فەرمانبەرەکەیە.

Where the analogy stops workingسنووری ئەم نموونەیە

A clerk checks once, at the end. Flutter can check at the end (validate) or while you type (autovalidate).

فەرمانبەر یەک جار، لە کۆتاییدا دەپشکنێت. Flutter دەتوانێت لە کۆتاییدا ⁦(validate)⁩ یان لە کاتی نووسیندا ⁦(autovalidate)⁩ بپشکنێت.

Forms on the web work the same way — see HTML form elements if you know HTML.

لە وێبیشدا بە هەمان شێوە کار دەکەن — ئەگەر HTML دەزانیت سەیری توخمەکانی فۆرم لە HTML بکە.

Quick checkپشکنینی خێراA screen asks for a name and checks that it is not empty before saving. Which widget fits the name box best?شاشەیەک داوای ناوێک دەکات و پێش پاشەکەوتکردن دەپشکنێت کە بەتاڵ نییە. کام بۆ خانەی ناوەکە باشترە؟

A first TextField and its decorationیەکەم TextField و decorationـەکەی

The course lists the attributes used most with a text field: decoration (the decoration around the field), border (a rounded rectangle around it), labelText (a label shown when the field is selected), hintText (a hint inside the field) and icon (an icon next to the field). One detail matters: only decoration belongs to TextField itself. The other four are properties of the InputDecoration object that you give to decoration.

وانەکە دەژمێرێت کە لەگەڵ زۆرترین بەکار دێن: decoration (ڕازاندنەوەی دەوری خانەکە)، border (لاکێشەیەکی گۆشەخڕ بە دەوریدا)، labelText ( کە کاتی هەڵبژاردنی خانەکە پیشان دەدرێت)، hintText (ڕێنماییەک لە ناو خانەکەدا) و icon ( لە تەنیشت خانەکەوە). وردەکارییەک گرنگە: تەنها decoration هی خودی TextFieldـە. چوارەکەی تر ئەو InputDecorationـەن کە دەیدەیت بە decoration.

The course's field, correctedخانەکەی وانەکە، چاککراوDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

class NameField extends StatelessWidget {
  const NameField({super.key});

  @override
  Widget build(BuildContext context) {
    return const Padding(
      padding: EdgeInsets.all(16),
      child: TextField(
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'User Name',
          hintText: 'Enter Your Name',
        ),
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 11

Everything drawn around the field goes into one InputDecoration.

هەموو ئەوەی بە دەوری خانەکەدا دەکێشرێت دەچێتە ناو یەک InputDecorationـەوە.

Lineدێڕی 12

A box with rounded corners instead of the default underline.

سندووقێک بە گۆشەی خڕ لە جیاتی هێڵی ژێرەوەی بنەڕەتی.

Lineدێڕی 13-14

The label names the field; the hint shows inside it while it is empty.

ناوی خانەکە دەبات؛ ڕێنماییەکە کاتێک بەتاڵە لە ناویدا دەردەکەوێت.

Three outlined text fields with labelled parts. 1: an empty focused field — labelText 'Name' on the border, hintText 'Enter your name' inside. 2: a field with a person icon outside (icon), a phone icon inside at the start (prefixIcon), the text '0750 123', a check icon at the end (suffixIcon), the box itself (border: OutlineInputBorder()), a helper line under it (helperText) and a counter 8/11 (maxLength). 3: an error state — red border and red label 'Email' around 'aram@', with the red errorText 'This does not look like an email address' from the validator.سێ خانەی دەقی هێڵدار کە بەشەکانیان ناونراون. ١: خانەیەکی بەتاڵی هەڵبژێردراو — labelText 'Name' لەسەر سنوورەکە، hintText 'Enter your name' لە ناویدا. ٢: خانەیەک بە ئایکۆنی کەس لە دەرەوە (icon)، ئایکۆنی تەلەفۆن لە ناوەوە لە سەرەتا (prefixIcon)، دەقی '0750 123'، ئایکۆنی ✓ لە کۆتایی (suffixIcon)، خودی سندووقەکە (border: OutlineInputBorder())، دێڕێکی یارمەتی لە ژێریدا (helperText) و ژمێرەری 8/11 (maxLength). ٣: دۆخی هەڵە — سنوور و لەیبڵی سووری 'Email' بە دەوری 'aram@'ـدا، لەگەڵ errorTextـی سووری 'This does not look like an email address' کە لە validatorـەوە دێت.
Everything around the typed text is set in InputDecoration.هەموو ئەوەی بە دەوری دەقە نووسراوەکەدایە لە InputDecorationـدا دیاری دەکرێت.CêIT
Quick checkپشکنینی خێراWhere does labelText belong?labelText هی کوێیە؟

A first TextField and its decorationیەکەم TextField و decorationـەکەی

More InputDecoration propertiesتایبەتمەندییەکانی زیاتری InputDecoration

InputDecoration has many more parts. Each one is optional; use only what helps the user.

InputDecoration بەشی زۆر زیاتری هەیە. هەر یەکێکیان ئارەزوومەندانەیە؛ تەنها ئەوە بەکار بهێنە کە یارمەتیی بەکارهێنەر دەدات.

PropertyWhat it showsچی پیشان دەدات
labelTextThe field's name; it floats up when the field is focused or filled.ناوی خانەکە؛ کاتێک خانەکە هەڵبژێردراوە یان پڕە بەرز دەبێتەوە.
hintTextA grey example inside the empty field.نموونەیەکی خۆڵەمێشی لە ناو خانە بەتاڵەکەدا.
helperTextA small help line under the field.دێڕێکی یارمەتیی بچووک لە ژێر خانەکەوە.
errorTextA red message under the field (a Form's validator sets it for you).پەیامێکی سوور لە ژێر خانەکەوە (validatorـی Form بۆت دایدەنێت).
iconAn icon outside the box, at the start. لە دەرەوەی سندووقەکە، لە سەرەتا.
prefixIcon / suffixIconIcons inside the box at the start / end (a suffix can be an IconButton, e.g. clear). لە ناو سندووقەکەدا لە سەرەتا / کۆتایی (پاشگر دەتوانێت IconButton بێت، بۆ نموونە clear).
prefixText / suffixTextFixed text such as +964 or IQD.دەقی جێگیر وەک +964 یان IQD.
borderOutlineInputBorder() (a box), UnderlineInputBorder() (a line, the default), InputBorder.none.OutlineInputBorder() (سندووق)، UnderlineInputBorder() (هێڵ، بنەڕەتی)، InputBorder.none.
filled / fillColorA background colour inside the field.ڕەنگێکی پاشبنەما لە ناو خانەکەدا.
A field with most partsخانەیەک بە زۆربەی بەشەکانییەوەDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

class PhoneField extends StatelessWidget {
  const PhoneField({super.key});

  @override
  Widget build(BuildContext context) {
    return const Padding(
      padding: EdgeInsets.all(16),
      child: TextField(
        maxLength: 11, // also shows a counter such as 4/11
        decoration: InputDecoration(
          icon: Icon(Icons.person), // outside the box
          prefixIcon: Icon(Icons.phone), // inside, at the start
          suffixIcon: Icon(Icons.check_circle), // inside, at the end
          labelText: 'Phone',
          hintText: '0750 123 4567',
          helperText: 'We call you only about your order',
          border: OutlineInputBorder(),
          filled: true, // a light background colour
        ),
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 11

maxLength belongs to the TextField itself; it stops typing at 11 and shows a counter.

maxLength هی خودی TextFieldـەکەیە؛ لە ١١دا نووسین ڕادەگرێت و پیشان دەدات.

Lineدێڕی 13-15

The three icon places.

سێ شوێنەکەی .

Lineدێڕی 18

Explain why you ask: users trust the form more.

ڕوونی بکەرەوە بۆچی داوای دەکەیت: بەکارهێنەران زیاتر متمانە بە دەکەن.

Quick checkپشکنینی خێراWhich property shows a grey example inside an empty field?کام نموونەیەکی خۆڵەمێشی لە ناو خانەیەکی بەتاڵدا پیشان دەدات؟

A first TextField and its decorationیەکەم TextField و decorationـەکەی

The right keyboard and safe inputکیبۆردی گونجاو و نێوخستەی سەلامەت

A phone shows a soft keyboard when a field gets the focus. Tell it which keyboard to show with keyboardType, what the Enter key should say with textInputAction, and hide a password with obscureText: true. inputFormatters can even stop wrong characters from being typed at all.

مۆبایل کاتێک خانەیەک هەڵدەبژێردرێت سەر شاشە پیشان دەدات. بە keyboardType پێی بڵێ کام پیشان بدات، بە textInputAction دوگمەی Enter چی بنووسێت و بە obscureText: true بشارەوە. inputFormatters تەنانەت دەتوانێت ڕێگە نەدات پیتی هەڵە بنووسرێت.

Four fields, four keyboardsچوار خانە، چوار کیبۆردDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class KeyboardFields extends StatelessWidget {
  const KeyboardFields({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        const TextField(
          keyboardType: TextInputType.emailAddress, // a keyboard with @
          textInputAction: TextInputAction.next, // the Enter key says Next
          autocorrect: false,
          decoration: InputDecoration(labelText: 'Email'),
        ),
        TextField(
          keyboardType: TextInputType.number, // digits only on the keyboard
          inputFormatters: [FilteringTextInputFormatter.digitsOnly],
          decoration: const InputDecoration(labelText: 'Age'),
        ),
        const TextField(
          obscureText: true, // shows dots instead of letters
          decoration: InputDecoration(labelText: 'Password'),
        ),
        const TextField(
          maxLines: 4, // a bigger box for an address or a message
          textCapitalization: TextCapitalization.sentences,
          decoration: InputDecoration(labelText: 'Address'),
        ),
      ],
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 13

An email keyboard has @ and . on the first page.

ئیمەیڵ @ و . لە پەڕەی یەکەمدا هەیە.

Lineدێڕی 20

Even a pasted 'abc' is refused: only digits get in.

تەنانەت 'abc'ـی لکێنراو ڕەت دەکرێتەوە: تەنها ژمارە دەچێتە ناوەوە.

Lineدێڕی 24

Dots instead of letters: nobody behind you can read it.

خاڵ لە جیاتی پیت: کەس لە پشتتەوە ناتوانێت بیخوێنێتەوە.

Lineدێڕی 28

Room for four lines.

شوێن بۆ چوار دێڕ.

Quick checkپشکنینی خێراWhich line hides the letters of a password?کام دێڕ پیتەکانی دەشارێتەوە؟

Two ways to get the textدوو ڕێگە بۆ وەرگرتنی دەقەکە

The course says Flutter lets you retrieve the typed text in mainly two ways: the controller and onChanged. Both work; they suit different jobs.

وانەکە دەڵێت Flutter بە شێوەی سەرەکی بە دوو ڕێگە ڕێگەت پێ دەدات دەقی نووسراو وەربگریت: controller و onChanged. هەردووکیان کار دەکەن؛ بۆ کاری جیاواز دەگونجێن.

PointخاڵonChangedTextEditingControlleronSubmitted
When you get the textکەی دەقەکە وەردەگریتAfter every change.دوای هەموو گۆڕانێک.Whenever you read .text.هەر کاتێک .text بخوێنیتەوە.When the user presses Enter/Done.کاتێک بەکارهێنەر ⁦Enter/Done⁩ دادەگرێت.
Can change the fieldدەتوانێت خانەکە بگۆڕێتNo.نا.Yes: .text = …, .clear().بەڵێ: .text = …، .clear().No.نا.
Extra workکاری زیادەNone.هیچ.Create once, dispose() at the end.یەک جار دروستی بکە، لە کۆتاییدا dispose().None.هیچ.
Good forباشە بۆLive search, counters.گەڕانی ڕاستەوخۆ، .Reading on a button press, filling or clearing a field.خوێندنەوە کاتی داگرتنی ، پڕکردنەوە یان بەتاڵکردنی خانە.A chat box or a search that runs on Enter.سندووقی گفتوگۆ یان گەڕانێک کە بە Enter کار دەکات.
Quick checkپشکنینی خێراA Send button must read a message and then empty the field. Which tool do you need? Send دەبێت نامەیەک بخوێنێتەوە و پاشان خانەکە بەتاڵ بکاتەوە. پێویستت بە کام ئامراز هەیە؟

Two ways to get the textدوو ڕێگە بۆ وەرگرتنی دەقەکە

onChanged: react to every letteronChanged: وەڵامدانەوە بۆ هەر پیتێک

The course calls onChanged the easiest way to retrieve the text field value. It is a callback: Flutter calls it after every change — each letter typed, deleted or pasted — and passes the whole new text. Use it when something must follow the typing live: a search list, a character counter, a greeting.

وانەکە onChanged ناو دەنێت ئاسانترین ڕێگە بۆ وەرگرتنی بەهای . ئەمە : Flutter دوای هەموو گۆڕانێک بانگی دەکات — هەر پیتێک بنووسرێت، بسڕدرێتەوە یان بلکێنرێت — و هەموو دەقە نوێیەکە دەنێرێت. کاتێک بەکاری بهێنە کە شتێک دەبێت ڕاستەوخۆ شوێن نووسینەکە بکەوێت: لیستی گەڕان، پیت، سڵاوێک.

A greeting that follows the typingسڵاوێک کە شوێن نووسین دەکەوێتDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

  @override
  State<LiveGreeting> createState() => _LiveGreetingState();
}

class _LiveGreetingState extends State<LiveGreeting> {
  String _name = '';

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          decoration: const InputDecoration(labelText: 'Name'),
          // called after every change: each letter typed or deleted
          onChanged: (String text) {
            setState(() => _name = text);
          },
        ),
        const SizedBox(height: 16),
        Text('Hello, $_name (${_name.characters.length} letters)'),
      ],
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 20-21

Store the new text in the State and rebuild, so the Text below changes.

دەقە نوێیەکە لە Stateـدا هەڵبگرە و دووبارە دروستی بکەرەوە، بۆ ئەوەی Textـەکەی خوارەوە بگۆڕێت.

Lineدێڕی 25

characters.length counts letters as people see them: an emoji such as 👍 counts as one, while _name.length would count it as two.

characters.length پیتەکان وەک ئەوەی خەڵک دەیانبینن دەژمێرێت: وەک 👍 بە یەک دەژمێردرێت، بەڵام _name.length بە دووی دەژمێرێت.

Quick checkپشکنینی خێراA user types Shilan (6 letters) and then deletes one letter. How many times was onChanged called?بەکارهێنەرێک Shilan (٦ پیت) دەنووسێت و پاشان پیتێک دەسڕێتەوە. onChanged چەند جار بانگ کرا؟

Two ways to get the textدوو ڕێگە بۆ وەرگرتنی دەقەکە

TextEditingController: read and write the textTextEditingController: خوێندنەوە و نووسینی دەقەکە

The course's other way is the controller: a TextEditingController object connected to the field with controller:. It always holds the current text in .text, so you can read it whenever you need it (for example when a button is pressed) and write to it (.text = …, .clear()).

ڕێگەکەی تری وانەکە controllerـە: TextEditingController کە بە controller: بە خانەکەوە دەبەسترێت. هەمیشە دەقی ئێستا لە .textـدا هەڵدەگرێت، بۆیە دەتوانیت هەر کاتێک پێویستت بوو بیخوێنیتەوە (بۆ نموونە کاتی داگرتنی ) و بینووسیت (.text = …، .clear()).

A controller created once and disposedcontrollerـێک کە یەک جار دروست دەکرێت و لادەبرێتDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

  @override
  State<CityForm> createState() => _CityFormState();
}

class _CityFormState extends State<CityForm> {
  // Created once, when the State is created — never inside build().
  final TextEditingController _cityController = TextEditingController();

  @override
  void dispose() {
    _cityController.dispose(); // free its resources
    super.dispose();
  }

  void _send() {
    final String city = _cityController.text.trim(); // read it now
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Delivery to $city')),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          controller: _cityController,
          decoration: InputDecoration(
            labelText: 'City',
            suffixIcon: IconButton(
              tooltip: 'Clear',
              icon: const Icon(Icons.clear),
              onPressed: () => _cityController.clear(), // write to it
            ),
          ),
        ),
        const SizedBox(height: 16),
        FilledButton(onPressed: _send, child: const Text('Send')),
      ],
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 12

Created once, with the State. Inside build it would be new on every rebuild and lose the text.

یەک جار لەگەڵ Stateـەکەدا دروست دەکرێت. لە ناو buildـدا لە هەموو دووبارە دروستکردنەوەیەکدا نوێ دەبێت و دەقەکە ون دەکات.

Lineدێڕی 15-17

When the screen goes away, dispose() frees the controller — see the State lifecycle.

کاتێک شاشەکە لادەچێت، dispose() controllerـەکە ئازاد دەکات — سەیری سووڕی ژیانی State بکە.

Lineدێڕی 21

Read the text only when you need it; trim() removes spaces at both ends.

دەقەکە تەنها کاتێک پێویستت بوو بخوێنەرەوە؛ trim() بۆشاییەکانی هەردوو سەر لادەبات.

Lineدێڕی 38

A controller can also change the field.

controller دەتوانێت خانەکەش بگۆڕێت.

Quick checkپشکنینی خێراWhy must a TextEditingController be created in the State (or initState) and not inside build()?بۆچی دەبێت TextEditingController لە Stateـدا (یان initState) دروست بکرێت نەک لە ناو build()؟

📱 FULL Flutter Beginner Course • Programming Basics / Widgets / Navigation / User Input / UIMitch Koko · Englishئینگلیزی · 1.6M viewsبینین · 46K likesلایک · Partبەشی 1:04:58–1:10:28 (ofلە 2:23:25)

Mitch Koko's calm beginner course in Dart and Flutter: variables, operators, if/else, switch, loops, functions, collections, a first screen and a counter.

کۆرسە ئارامەکەی ⁦Mitch Koko⁩ بۆ سەرەتاییەکان لە و : ، ، if/else، switch، ، ، List/Set/Map، یەکەم شاشە و .

Watch 1:04:58–1:10:28, the 'user input • TEXTFIELD' chapter: a TextField, a TextEditingController and a button that reads controller.text.

لە ⁦1:04:58⁩ تا ⁦1:10:28⁩ سەیر بکە، بەشی user input • TEXTFIELD: TextField، TextEditingController و کە controller.text دەخوێنێتەوە.

Form, TextFormField and validationForm، TextFormField و پشتڕاستکردنەوە

A Form groups fields so they can be checked together. Each TextFormField gets a validator: a function that receives the field's text and returns an error message if something is wrong, or null if it is fine. To reach the form from a button, give the Form a GlobalKey<FormState>; _formKey.currentState!.validate() then runs every validator, shows the messages in red under the fields, and returns true only if all of them returned null.

Form خانەکان کۆ دەکاتەوە بۆ ئەوەی پێکەوە بپشکنرێن. هەر TextFormFieldـێک validatorـێک وەردەگرێت: کە دەقی خانەکە وەردەگرێت و ئەگەر شتێک هەڵە بێت دەگەڕێنێتەوە، یان ئەگەر باش بێت null. بۆ گەیشتن بە لە ، GlobalKey<FormState>ـێک بدە بە Formـەکە؛ پاشان _formKey.currentState!.validate() هەموو validatorـەکان ڕادەکات، پەیامەکان بە سوور لە ژێر خانەکانەوە پیشان دەدات و تەنها ئەگەر هەموویان nullـیان گەڕاندبێتەوە true دەگەڕێنێتەوە.

A form with one validated fieldفۆرمێک بە یەک خانەی پشکنراوەوەDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

  @override
  State<NameForm> createState() => _NameFormState();
}

class _NameFormState extends State<NameForm> {
  // The key that lets us reach the Form's state from the button.
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            decoration: const InputDecoration(labelText: 'Name'),
            // Return an error message, or null when the value is fine.
            validator: (String? value) {
              if (value == null || value.trim().isEmpty) {
                return 'Please enter your name';
              }
              return null;
            },
          ),
          const SizedBox(height: 16),
          ElevatedButton(
            onPressed: () {
              // Runs every validator; true only if all return null.
              if (_formKey.currentState!.validate()) {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('Saved')),
                );
              }
            },
            child: const Text('Submit'),
          ),
        ],
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 12

Created once in the State. It is a GlobalKey<FormState>, not a key of your own State class.

یەک جار لە Stateـدا دروست دەکرێت. GlobalKey<FormState>ـە، نەک Stateـی خۆت.

Lineدێڕی 24-28

An error message, or null for valid.

، یان null بۆ دروست.

Lineدێڕی 35

Runs all validators; true only if every field is valid.

هەموو validatorـەکان ڕادەکات؛ تەنها ئەگەر هەموو خانەیەک دروست بێت true.

What validate() does⁦validate()⁩ چی دەکات
  1. The user presses Submit.

    بەکارهێنەر Submit دادەگرێت.

  2. validate() calls every field's validator with its current text.

    validate() validatorـی هەموو خانەیەک بە دەقی ئێستای بانگ دەکات.

  3. Each validator returns a message (wrong) or null (right).

    هەر validatorـێک پەیامێک (هەڵە) یان null (ڕاست) دەگەڕێنێتەوە.

  4. The Form rebuilds: messages appear in red under the wrong fields.

    Formـەکە دووبارە دروست دەبێتەوە: پەیامەکان بە سوور لە ژێر خانە هەڵەکانەوە دەردەکەون.

  5. validate() returns true only if no field had a message — then save or send the data.

    validate() تەنها ئەگەر هیچ خانەیەک پەیامی نەبووبێت true دەگەڕێنێتەوە — ئەوکاتە پاشەکەوت بکە یان بینێرە.

Quick checkپشکنینی خێراA validator returns '' (an empty string) for a valid value. What happens?validatorـێک بۆ بەهایەکی دروست '' ( بەتاڵ) دەگەڕێنێتەوە. چی ڕوو دەدات؟

Form, TextFormField and validationForm، TextFormField و پشتڕاستکردنەوە

Writing validatorsنووسینی validator

A validator is an ordinary function String? Function(String? value). Keep each rule small, give a message that says how to fix the problem, and reuse the functions in many forms. Three common rules:

validator ئاسایی String? Function(String? value)ـە. هەر یاسایەک بچووک ڕابگرە، پەیامێک بدە کە بڵێت چۆن کێشەکە چاک بکرێت و لە چەند دووبارە بەکار بهێنەوە. سێ یاسای باو:

Reusable validators (checked with dart run)validatorـی دووبارە بەکارهاتوو (بە ⁦dart run⁩ پشکنراوە)DART
// Small validator functions you can reuse in many forms.

String? requiredField(String? value) {
  if (value == null || value.trim().isEmpty) return 'This field is required';
  return null;
}

String? emailField(String? value) {
  final v = value?.trim() ?? '';
  if (v.isEmpty) return 'Please enter your email';
  // A simple check: something@something.something
  final ok = RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$').hasMatch(v);
  return ok ? null : 'This does not look like an email address';
}

String? ageField(String? value) {
  final age = int.tryParse(value ?? ''); // null if it is not a number
  if (age == null) return 'Please enter a number';
  if (age < 16 || age > 99) return 'Age must be between 16 and 99';
  return null;
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 4

trim() first: a field with only spaces is empty too.

سەرەتا trim(): خانەیەک کە تەنها بۆشایی تێدایە ئەویش بەتاڵە.

Lineدێڕی 12

A RegExp is a text pattern: here some characters, @, some characters, a dot, some characters (no spaces). It catches typos, but only sending an email proves an address is real.

RegExp قاڵبێکی دەقە: لێرەدا چەند پیت یان هێمایەک، @، چەند پیت یان هێمایەک، خاڵ، چەند پیت یان هێمایەک (بێ بۆشایی). هەڵەی نووسین دەگرێت، بەڵام تەنها ناردنی ئیمەیڵێک دەیسەلمێنێت کە ناونیشانێک ڕاستەقینەیە.

Lineدێڕی 17

int.tryParse returns null instead of crashing on 'abc'.

int.tryParse لە جیاتی تەقینەوە بە 'abc'، null دەگەڕێنێتەوە.

Use a validator by name: validator: emailField. To combine it with something else, wrap it: validator: (v) => requiredField(v) ?? ageField(v) — the ?? takes the first message that is not null.

validatorـێک بە ناو بەکار بهێنە: validator: emailField. بۆ تێکەڵکردنی لەگەڵ شتێکی تر، بیپێچەوە: validator: (v) => requiredField(v) ?? ageField(v) — ?? یەکەم پەیام وەردەگرێت کە null نییە.

Quick checkپشکنینی خێراWhat does int.tryParse('7a') return?int.tryParse('7a') چی دەگەڕێنێتەوە؟

Form, TextFormField and validationForm، TextFormField و پشتڕاستکردنەوە

When to check: autovalidateModeکەی بپشکنرێت: autovalidateMode

By default a Form checks only when you call validate(). autovalidateMode (on the Form or on one field) checks earlier:

بە شێوەی بنەڕەتی Form تەنها کاتێک validate() بانگ دەکەیت دەپشکنێت. autovalidateMode (لەسەر Form یان لەسەر یەک خانە) زووتر دەپشکنێت:

AutovalidateModeChecks…دەپشکنێت…
disabledOnly on validate() (the default).تەنها لەسەر validate() (بنەڕەتی).
onUserInteractionAfter the user has changed a field, on every change.دوای ئەوەی بەکارهێنەر خانەیەکی گۆڕی، لە هەموو گۆڕانێکدا.
onUnfocusWhen the user leaves a field.کاتێک بەکارهێنەر خانەیەک بەجێ دەهێڵێت.
alwaysAll the time, even before the user types — red errors on an empty new form.هەمیشە، تەنانەت پێش ئەوەی بەکارهێنەر بنووسێت — سوور لەسەر نوێی بەتاڵ.
Quick checkپشکنینی خێراWhich mode shows red errors on a brand-new, empty form?کام دۆخ سوور لەسەر تازە و بەتاڵ پیشان دەدات؟

A login form with validationفۆرمێکی چوونەژوورەوە بە پشتڕاستکردنەوەوە

Everything together: two fields with controllers, keyboards and validators, a password that can be shown or hidden, checks while typing, and one button. The animation shows the two ideas of this lesson — onChanged follows every letter, and validate() turns an empty field red:

هەموو شتێک پێکەوە: دوو خانە بە controller، و validatorـەوە، کە دەتوانرێت پیشان بدرێت یان بشاردرێتەوە، پشکنین لە کاتی نووسیندا و یەک . ئەم جووڵەیە دوو بیرۆکەکەی ئەم وانەیە پیشان دەدات — onChanged شوێن هەموو پیتێک دەکەوێت و validate() خانەیەکی بەتاڵ سوور دەکات:

Five frames of a phone screen 'Sign in' with a Name field, a 'Hello, …' line, a Password field and a Submit button; a code line above the phone. 1: the empty form (onChanged: (text) => setState(() => _name = text)). 2: 'A' is typed — onChanged('A') — and the line says 'Hello, A'. 3: 'Aram' — onChanged ran once per letter — 'Hello, Aram'. 4: Submit with no password: validate() is false, the Password field is red with 'Please enter your password'. 5: a password is typed and Submit pressed again: validate() is true and a snackbar says 'Welcome, Aram'.
Five frames of a phone screen 'Sign in' with a Name field, a 'Hello, …' line, a Password field and a Submit button; a code line above the phone. 1: the empty form (onChanged: (text) => setState(() => _name = text)). 2: 'A' is typed — onChanged('A') — and the line says 'Hello, A'. 3: 'Aram' — onChanged ran once per letter — 'Hello, Aram'. 4: Submit with no password: validate() is false, the Password field is red with 'Please enter your password'. 5: a password is typed and Submit pressed again: validate() is true and a snackbar says 'Welcome, Aram'.
onChanged follows every letter; validate() shows the red error.onChanged شوێن هەموو پیتێک دەکەوێت؛ ⁦validate()⁩ سوورەکە پیشان دەدات.CêIT
lib/main.dart — a login page⁦lib/main.dart⁩ — پەڕەی چوونەژوورەوەlib/main.dartDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

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

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _hidePassword = true;

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

  void _logIn() {
    if (!_formKey.currentState!.validate()) return; // show the errors
    // Here a real app sends the data to its server over HTTPS.
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Welcome, ${_emailController.text.trim()}')),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Log in')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Form(
          key: _formKey,
          autovalidateMode: AutovalidateMode.onUserInteraction,
          child: Column(
            children: [
              TextFormField(
                controller: _emailController,
                keyboardType: TextInputType.emailAddress,
                textInputAction: TextInputAction.next,
                autofillHints: const [AutofillHints.email],
                decoration: const InputDecoration(
                  labelText: 'Email',
                  prefixIcon: Icon(Icons.email_outlined),
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  final v = value?.trim() ?? '';
                  if (v.isEmpty) return 'Please enter your email';
                  if (!v.contains('@')) return 'An email address has an @';
                  return null;
                },
              ),
              const SizedBox(height: 16),
              TextFormField(
                controller: _passwordController,
                obscureText: _hidePassword,
                textInputAction: TextInputAction.done,
                autofillHints: const [AutofillHints.password],
                onFieldSubmitted: (_) => _logIn(),
                decoration: InputDecoration(
                  labelText: 'Password',
                  prefixIcon: const Icon(Icons.lock_outline),
                  border: const OutlineInputBorder(),
                  suffixIcon: IconButton(
                    tooltip: _hidePassword ? 'Show password' : 'Hide password',
                    icon: Icon(
                      _hidePassword ? Icons.visibility : Icons.visibility_off,
                    ),
                    onPressed: () =>
                        setState(() => _hidePassword = !_hidePassword),
                  ),
                ),
                // At log-in only check that something was typed:
                // length rules belong to the sign-up form.
                validator: (value) => (value == null || value.isEmpty)
                    ? 'Please enter your password'
                    : null,
              ),
              const SizedBox(height: 24),
              SizedBox(
                width: double.infinity,
                child: FilledButton(onPressed: _logIn, child: const Text('Log in')),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 13-16

The form key, two controllers and one piece of state, all created once.

، دوو controller و یەک پارچە ، هەموویان یەک جار دروست دەکرێن.

Lineدێڕی 19-22

Both controllers are disposed.

هەردوو controllerـەکە dispose دەکرێن.

Lineدێڕی 37

When the keyboard opens, the form can scroll instead of overflowing.

کاتێک دەکرێتەوە، دەتوانێت بکات لە جیاتی ڕژانە دەرەوە.

Lineدێڕی 41

Check while the user types, after the first change.

لە کاتی نووسیندا بپشکنە، دوای یەکەم گۆڕان.

Lineدێڕی 48

Lets the phone's password manager fill the field.

ڕێگە دەدات مۆبایلەکە خانەکە پڕ بکاتەوە.

Lineدێڕی 64

Dots, or the real letters when the eye button is tapped.

خاڵ، یان پیتە ڕاستەقینەکان کاتێک دەست لە چاو دەدرێت.

Lineدێڕی 83

At log-in only check that a password was typed; length rules belong to the sign-up form.

لە کاتی تەنها بپشکنە کە نووسراوە؛ یاساکانی درێژی هی .

Quick checkپشکنینی خێراIn the login page, what does onFieldSubmitted: (_) => _logIn() on the password field do?لە پەڕەی ، onFieldSubmitted: (_) => _logIn() لەسەر خانەی چی دەکات؟

A login form with validationفۆرمێکی چوونەژوورەوە بە پشتڕاستکردنەوەوە

The app checks, the server decidesئەپەکە دەپشکنێت، ڕاژەکارەکە بڕیار دەدات

Quick checkپشکنینی خێراThe app's validator rejects passwords shorter than 15 characters. Is the account safe from short passwords?validatorـی کورتتر لە ١٥ پیت ڕەت دەکاتەوە. ئایا هەژمارەکە لە کورت پارێزراوە؟

Common mistakesهەڵە باوەکان

MistakeهەڵەWhat happensچی ڕوو دەداتFixچاککردن
labelText, hintText, border written directly on TextField.labelText، hintText، border ڕاستەوخۆ لەسەر TextField نووسراون.Compile error: no such parameter.: ئەم نییە.Put them in decoration: InputDecoration(...).بیانخە ناو decoration: InputDecoration(...).
A TextEditingController created inside build().TextEditingControllerـێک لە ناو build()ـدا دروست کراوە.The text disappears after a rebuild.دوای دووبارە دروستکردنەوە دەقەکە ون دەبێت.Create it once in the State; dispose it.یەک جار لە Stateـدا دروستی بکە؛ disposeـی بکە.
Forgetting dispose().لەبیرکردنی dispose().The controller keeps its resources after the screen is gone.controllerـەکە دوای ڕۆیشتنی شاشەکە خۆی دەهێڵێتەوە._controller.dispose() in the State's dispose()._controller.dispose() لە dispose()ـی Stateـدا.
A validator returns '' for valid input.validatorـێک بۆ دروست '' دەگەڕێنێتەوە.The form is never valid. هەرگیز دروست نابێت.Return null when the value is fine.کاتێک بەهاکە باشە null بگەڕێنەوە.
_formKey.currentState! when the Form is not in the tree._formKey.currentState! کاتێک Form لە درەختەکەدا نییە.Null check error at run time. پشکنینی null لە کاتی جێبەجێکردندا.Give the key to the Form that contains the button's fields. بدە بەو Formـەی خانەکانی تێدایە.
A TextField directly inside a Row.TextFieldـێک ڕاستەوخۆ لە ناو Rowـێکدا.Error: An InputDecorator … cannot have an unbounded width.: ⁦An InputDecorator⁩ … ⁦cannot have an unbounded width⁩.Wrap it in Expanded (or give it a width).بیخە ناو Expanded (یان پانییەکی بدەیتێ).
A long form in a plain Column. درێژ لە Columnـێکی سادەدا.The keyboard covers the lower fields; overflow stripes. خانەکانی خوارەوە دادەپۆشێت؛ هێڵی overflow.Wrap the form in SingleChildScrollView. بخە ناو SingleChildScrollView.
Trusting the app's validation alone.تەنها متمانەکردن بە .Bad data reaches the server through other paths. خراپ لە ڕێگەی تر دەگاتە .Validate again on the server.لەسەر دووبارە بپشکنەوە.

Exercisesڕاهێنانەکان

Exerciseڕاهێنان1. Repair the course's code١. کۆدی وانەکە چاک بکەرەوە

Make the course's two snippets work: the TextField with border, label and hint, and the controller that reads the text. Put the controller in a StatefulWidget and dispose it.

دوو پارچە کۆدەکەی وانەکە کارا بکە: TextFieldـەکە بە ، و ڕێنماییەوە و ئەو controllerـەی دەقەکە دەخوێنێتەوە. controllerـەکە بخە ناو StatefulWidgetـێکەوە و disposeـی بکە.

The course's TextFieldTextFieldـی وانەکەDART
TextField (
  decoration: InputDecoration(
  border: OutlineInputBorder(),
  labelText: User Name',
  hintText: 'Enter Your Name'
),)
The course's controllercontrollerـی وانەکەDART
TextEditingController mycontroller = TextEditingController();
TextField(controller: mycontroller)
String data = mycontroller.text
Show answerوەڵامەکە پیشان بدە

The field: add the missing quote, close InputDecoration( and TextField( properly. The controller: create it once as a field of the State, read .text when needed (with ;), and dispose it.

خانەکە: ئەو 'ـەی ونبووە زیاد بکە و InputDecoration( و TextField( بە دروستی دابخە. controller: یەک جار وەک خانەیەکی State دروستی بکە، .text کاتێک پێویستە بخوێنەرەوە (بە ;) و disposeـی بکە.

Fixed (the State part)چاککراو (بەشی State)DART
class _NameState extends State<NameBox> {
  final TextEditingController nameController = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: nameController,
      decoration: const InputDecoration(
        border: OutlineInputBorder(),
        labelText: 'User Name',
        hintText: 'Enter Your Name',
      ),
    );
  }

  String readName() => nameController.text; // the typed name
}
Exerciseڕاهێنان2. A live city search٢. گەڕانی ڕاستەوخۆی شار

Show a search field above a list of five Kurdish cities. As the user types, the list shows only the cities that contain the typed text (upper or lower case does not matter).

خانەیەکی گەڕان لە سەرووی لیستێکی پێنج شاری کوردستانەوە پیشان بدە. کاتێک بەکارهێنەر دەنووسێت، لیستەکە تەنها ئەو شارانە پیشان دەدات کە دەقە نووسراوەکەیان تێدایە (پیتی گەورە یان بچووک گرنگ نییە).

Show answerوەڵامەکە پیشان بدە
One possible answerوەڵامێکی گونجاوDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

  @override
  State<CitySearch> createState() => _CitySearchState();
}

class _CitySearchState extends State<CitySearch> {
  static const _cities = ['Erbil', 'Sulaymaniyah', 'Duhok', 'Halabja', 'Zakho'];
  String _query = '';

  @override
  Widget build(BuildContext context) {
    final matches = _cities
        .where((c) => c.toLowerCase().contains(_query.toLowerCase()))
        .toList();
    return Column(
      children: [
        TextField(
          decoration: const InputDecoration(
            prefixIcon: Icon(Icons.search),
            hintText: 'Search a city',
          ),
          onChanged: (text) => setState(() => _query = text),
        ),
        Expanded(
          child: ListView(
            children: [for (final c in matches) ListTile(title: Text(c))],
          ),
        ),
      ],
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 17

Compare both in lower case.

هەردووکیان بە پیتی بچووک بەراورد بکە.

Lineدێڕی 26

onChanged is the right tool: the list follows every letter.

onChanged ئامرازە گونجاوەکەیە: لیستەکە شوێن هەموو پیتێک دەکەوێت.

Exerciseڕاهێنان3. Repeat the password٣. تێپەڕەوشەکە دووبارە بکەرەوە

Build a sign-up form with Password (at least 15 characters) and Repeat password, which must match the first one.

دروست بکە بە Password (لانیکەم ١٥ پیت) و ⁦Repeat password⁩ کە دەبێت وەک یەکەم بێت.

Show answerوەڵامەکە پیشان بدە
One possible answerوەڵامێکی گونجاوDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

  @override
  State<RegisterForm> createState() => _RegisterFormState();
}

class _RegisterFormState extends State<RegisterForm> {
  final _formKey = GlobalKey<FormState>();
  final _passwordController = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
            controller: _passwordController,
            obscureText: true,
            decoration: const InputDecoration(labelText: 'Password'),
            validator: (v) => (v == null || v.characters.length < 15)
                ? 'Use at least 15 characters'
                : null,
          ),
          TextFormField(
            obscureText: true,
            decoration: const InputDecoration(labelText: 'Repeat password'),
            // compare with the text of the first field
            validator: (v) => v != _passwordController.text
                ? 'The two passwords are different'
                : null,
          ),
          const SizedBox(height: 16),
          FilledButton(
            onPressed: () => _formKey.currentState!.validate(),
            child: const Text('Create account'),
          ),
        ],
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 30

The length rule belongs here, at sign-up.

یاسای درێژی لێرەدایە، لە کاتی .

Lineدێڕی 38

The second validator reads the first field through its controller.

validatorـی دووەم خانەی یەکەم لە ڕێگەی controllerـەکەیەوە دەخوێنێتەوە.

Exerciseڕاهێنان4. An age field٤. خانەی تەمەن

Write a TextFormField for an age between 16 and 99 that shows the number keyboard and refuses letters.

TextFormFieldـێک بۆ تەمەنێک لە نێوان ١٦ و ٩٩دا بنووسە کە ژمارە پیشان دەدات و پیت ڕەت دەکاتەوە.

Hintئاماژە

Combine keyboardType, inputFormatters and the ageField validator.

keyboardType، inputFormatters و validatorـی ageField تێکەڵ بکە.

Show answerوەڵامەکە پیشان بدە
One possible answerوەڵامێکی گونجاوDART
TextFormField(
  keyboardType: TextInputType.number,
  inputFormatters: [FilteringTextInputFormatter.digitsOnly],
  decoration: const InputDecoration(labelText: 'Age'),
  validator: ageField, // from the validators above
)
Exerciseڕاهێنان5. Explain dispose٥. dispose ڕوون بکەرەوە

A classmate says: My app works without dispose(), so I do not need it. Answer in two or three sentences.

هاوپۆلێک دەڵێت: بەبێ dispose() کار دەکات، بۆیە پێویستم پێی نییە. بە دوو یان سێ ڕستە وەڵام بدەرەوە.

Show answerوەڵامەکە پیشان بدە

A controller holds resources and listeners. Without dispose() they stay alive after the screen is closed; one screen hardly shows it, but opening and closing screens many times wastes memory and can call listeners of widgets that are gone. Flutter's docs say to dispose every controller you create.

controller و گوێگر هەڵدەگرێت. بەبێ dispose() دوای داخستنی شاشەکە زیندوو دەمێننەوە؛ یەک شاشە بە ئەستەم پیشانی دەدات، بەڵام کردنەوە و داخستنی شاشەکان بە چەندین جار بیرگە بەفیڕۆ دەدات و دەتوانێت گوێگری ئەو نەماون بانگ بکات. بەڵگەنامەکانی Flutter دەڵێن هەموو controllerـێک کە دروستی دەکەیت dispose بکە.

Quick checkپشکنینی خێراWhich method on the form key runs all validators?کام لەسەر هەموو validatorـەکان ڕادەکات؟

Summaryپوختە

  • TextField takes typed text; TextFormField adds a validator and works inside a Form.
  • decoration: InputDecoration(...) holds labelText, hintText, helperText, errorText, icon, prefixIcon/suffixIcon and border; keyboardType, obscureText, maxLength and inputFormatters belong to the field.
  • Two ways to get the text: onChanged (after every change) or a TextEditingController (.text, .clear()), created once and disposed.
  • A validator returns an error message or null; GlobalKey<FormState> + validate() checks the whole form; autovalidateMode checks earlier.
  • Validation in the app helps the user; the server must check again.
  • TextField دەقی نووسراو وەردەگرێت؛ TextFormField validatorـێک زیاد دەکات و لە ناو Formـێکدا کار دەکات.
  • decoration: InputDecoration(...) labelText، hintText، helperText، errorText، icon، ⁦prefixIcon/suffixIcon⁩ و border هەڵدەگرێت؛ keyboardType، obscureText، maxLength و inputFormatters هی خانەکەن.
  • دوو ڕێگە بۆ وەرگرتنی دەقەکە: onChanged (دوای هەموو گۆڕانێک) یان TextEditingController (.text، .clear()) کە یەک جار دروست دەکرێت و dispose دەکرێت.
  • validator یان null دەگەڕێنێتەوە؛ GlobalKey<FormState> + validate() هەموو دەپشکنێت؛ autovalidateMode زووتر دەپشکنێت.
  • لە یارمەتیی بەکارهێنەر دەدات؛ دەبێت دووبارە بپشکنێتەوە.
Review questionsپرسیارەکانی پێداچوونەوە
When do you choose a controller instead of onChanged?کەی controller لە جیاتی onChanged هەڵدەبژێریت؟

When you read the text at a particular moment (a button press) or must change it from code (fill in, clear).

کاتێک دەقەکە لە ساتێکی دیاریکراودا دەخوێنیتەوە (داگرتنی ) یان دەبێت لە کۆدەوە بیگۆڕیت (پڕکردنەوە، بەتاڵکردنەوە).

What does a validator return for a valid value?validator بۆ بەهایەکی دروست چی دەگەڕێنێتەوە؟

null. Any string, even an empty one, is shown as an error.

null. هەر ، تەنانەت بەتاڵیش، وەک پیشان دەدرێت.

Why is the form key a GlobalKey<FormState>?بۆچی کلیلەکەی فۆرم ⁦GlobalKey<FormState>⁩ـە؟

It lets code outside the Form (a button's onPressed) reach the Form's state and call validate(), save() or reset().

ڕێگە دەدات کۆدێک لە دەرەوەی ⁦Form (onPressed⁩ـی ) بگاتە stateـی Formـەکە و ⁦validate()⁩، ⁦save()⁩ یان ⁦reset()⁩ بانگ بکات.

Lesson complete!وانەکە تەواو بوو!

Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.

Key termsزاراوە سەرەکییەکان

Next lessonوانەی داهاتوو

Splash Screensشاشەکانی دەستپێک

References and further readingسەرچاوەکان و خوێندنەوەی زیاتر

This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.