// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'framework.dart'; import 'navigator.dart'; import 'restoration.dart'; import 'restoration_properties.dart'; import 'will_pop_scope.dart'; /// An optional container for grouping together multiple form field widgets /// (e.g. [TextField] widgets). /// /// Each individual form field should be wrapped in a [FormField] widget, with /// the [Form] widget as a common ancestor of all of those. Call methods on /// [FormState] to save, reset, or validate each [FormField] that is a /// descendant of this [Form]. To obtain the [FormState], you may use [Form.of] /// with a context whose ancestor is the [Form], or pass a [GlobalKey] to the /// [Form] constructor and call [GlobalKey.currentState]. /// /// {@tool dartpad} /// This example shows a [Form] with one [TextFormField] to enter an email /// address and an [ElevatedButton] to submit the form. A [GlobalKey] is used here /// to identify the [Form] and validate input. /// ///  /// /// ** See code in examples/api/lib/widgets/form/form.0.dart ** /// {@end-tool} /// /// See also: /// /// * [GlobalKey], a key that is unique across the entire app. /// * [FormField], a single form field widget that maintains the current state. /// * [TextFormField], a convenience widget that wraps a [TextField] widget in a [FormField]. class Form extends StatefulWidget { /// Creates a container for form fields. /// /// The [child] argument must not be null. const Form({ Key? key, required this.child, this.onWillPop, this.onChanged, AutovalidateMode? autovalidateMode, }) : assert(child != null), autovalidateMode = autovalidateMode ?? AutovalidateMode.disabled, super(key: key); /// Returns the closest [FormState] which encloses the given context. /// /// Typical usage is as follows: /// /// ```dart /// FormState form = Form.of(context); /// form.save(); /// ``` static FormState? of(BuildContext context) { final _FormScope? scope = context.dependOnInheritedWidgetOfExactType<_FormScope>(); return scope?._formState; } /// The widget below this widget in the tree. /// /// This is the root of the widget hierarchy that contains this form. /// /// {@macro flutter.widgets.ProxyWidget.child} final Widget child; /// Enables the form to veto attempts by the user to dismiss the [ModalRoute] /// that contains the form. /// /// If the callback returns a Future that resolves to false, the form's route /// will not be popped. /// /// See also: /// /// * [WillPopScope], another widget that provides a way to intercept the /// back button. final WillPopCallback? onWillPop; /// Called when one of the form fields changes. /// /// In addition to this callback being invoked, all the form fields themselves /// will rebuild. final VoidCallback? onChanged; /// Used to enable/disable form fields auto validation and update their error /// text. /// /// {@macro flutter.widgets.FormField.autovalidateMode} final AutovalidateMode autovalidateMode; @override FormState createState() => FormState(); } /// State associated with a [Form] widget. /// /// A [FormState] object can be used to [save], [reset], and [validate] every /// [FormField] that is a descendant of the associated [Form]. /// /// Typically obtained via [Form.of]. class FormState extends State