Commit 7d346dd1 authored by Matt Perry's avatar Matt Perry Committed by GitHub

Improve docs for Input and Form and friends. (#7208)

Fixes https://github.com/flutter/flutter/issues/7017
parent 5a864ded
...@@ -18,7 +18,10 @@ export 'package:flutter/services.dart' show TextInputType; ...@@ -18,7 +18,10 @@ export 'package:flutter/services.dart' show TextInputType;
const Duration _kTransitionDuration = const Duration(milliseconds: 200); const Duration _kTransitionDuration = const Duration(milliseconds: 200);
const Curve _kTransitionCurve = Curves.fastOutSlowIn; const Curve _kTransitionCurve = Curves.fastOutSlowIn;
/// A simple text input field. /// A simple undecorated text input field.
///
/// If you want decorations as specified in the Material spec (most likely),
/// use [Input] instead.
/// ///
/// This widget is comparable to [Text] in that it does not include a margin /// This widget is comparable to [Text] in that it does not include a margin
/// or any decoration outside the text itself. It is useful for applications, /// or any decoration outside the text itself. It is useful for applications,
...@@ -35,6 +38,7 @@ const Curve _kTransitionCurve = Curves.fastOutSlowIn; ...@@ -35,6 +38,7 @@ const Curve _kTransitionCurve = Curves.fastOutSlowIn;
/// ///
/// * [Input], which adds a label, a divider below the text field, and support for /// * [Input], which adds a label, a divider below the text field, and support for
/// an error message. /// an error message.
/// * [RawInput], a text field that does not require [Material] design.
class InputField extends StatefulWidget { class InputField extends StatefulWidget {
InputField({ InputField({
Key key, Key key,
...@@ -143,7 +147,6 @@ class _InputFieldState extends State<InputField> { ...@@ -143,7 +147,6 @@ class _InputFieldState extends State<InputField> {
]; ];
if (config.hintText != null && value.text.isEmpty) { if (config.hintText != null && value.text.isEmpty) {
TextStyle hintStyle = textStyle.copyWith(color: themeData.hintColor); TextStyle hintStyle = textStyle.copyWith(color: themeData.hintColor);
stackChildren.add( stackChildren.add(
new Positioned( new Positioned(
...@@ -373,13 +376,23 @@ class _InputContainerState extends State<InputContainer> { ...@@ -373,13 +376,23 @@ class _InputContainerState extends State<InputContainer> {
/// ///
/// Requires one of its ancestors to be a [Material] widget. /// Requires one of its ancestors to be a [Material] widget.
/// ///
/// See also: /// When using inside a [Form], consider using [InputFormField] instead.
/// ///
/// * <https://material.google.com/components/text-fields.html> /// Assuming that the input is already focused, the basic data flow for
/// retrieving user input is:
/// 1. User taps a character on the keyboard.
/// 2. The [onChanged] callback is called with the current [InputValue].
/// 3. Perform any necessary logic/validation on the current input value.
/// 4. Update the state of the [Input] widget accordingly through [State.setState].
/// ///
/// For a detailed guide on using the input widget, see: /// For most cases, we recommend that you use the [Input] class within a
/// [StatefulWidget] so you can save and operate on the current value of the
/// input.
/// ///
/// * <https://flutter.io/text-input/> /// See also:
///
/// * <https://material.google.com/components/text-fields.html>
/// * [InputFormField], which simplifies steps 2-4 above.
class Input extends StatefulWidget { class Input extends StatefulWidget {
/// Creates a text input field. /// Creates a text input field.
/// ///
...@@ -520,6 +533,76 @@ class _InputState extends State<Input> { ...@@ -520,6 +533,76 @@ class _InputState extends State<Input> {
} }
/// A [FormField] that contains an [Input]. /// A [FormField] that contains an [Input].
///
/// This is a convenience widget that simply wraps an [Input] widget in a
/// [FormField]. The [FormField] maintains the current value of the [Input] so
/// that you don't need to manage it yourself.
///
/// A [Form] ancestor is not required. The [Form] simply makes it easier to
/// save, reset, or validate multiple fields at once. To use without a [Form],
/// pass a [GlobalKey] to the constructor and use [GlobalKey.currentState] to
/// save or reset the form field.
///
/// To see the use of [InputFormField], compare these two ways of a implementing
/// a simple two text field form.
///
/// Using [InputFormField]:
///
/// ```dart
/// String _firstName, _lastName;
/// GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
/// ...
/// new Form(
/// key: _formKey,
/// child: new Row(
/// children: <Widget>[
/// new InputFormField(
/// labelText: 'First Name',
/// onSaved: (InputValue value) { _firstName = value.text; }
/// ),
/// new InputFormField(
/// labelText: 'Last Name',
/// onSaved: (InputValue value) { _lastName = value.text; }
/// ),
/// new RaisedButton(
/// child: new Text('SUBMIT'),
/// // Instead of _formKey.currentState, you could wrap the
/// // RaisedButton in a Builder widget to get access to a BuildContext,
/// // and use Form.of(context).
/// onPressed: () { _formKey.currentState.save(); },
/// ),
/// )
/// )
/// ```
///
/// Using [Input] directly:
///
/// ```dart
/// String _firstName, _lastName;
/// InputValue _firstNameValue = const InputValue();
/// InputValue _lastNameValue = const InputValue();
/// ...
/// new Row(
/// children: <Widget>[
/// new Input(
/// value: _firstNameValue,
/// labelText: 'First Name',
/// onChanged: (InputValue value) { setState( () { _firstNameValue = value; } ); }
/// ),
/// new Input(
/// value: _lastNameValue,
/// labelText: 'Last Name',
/// onChanged: (InputValue value) { setState( () { _lastNameValue = value; } ); }
/// ),
/// new RaisedButton(
/// child: new Text('SUBMIT'),
/// onPressed: () {
/// _firstName = _firstNameValue.text;
/// _lastName = _lastNameValue.text;
/// },
/// ),
/// )
/// ```
class InputFormField extends FormField<InputValue> { class InputFormField extends FormField<InputValue> {
InputFormField({ InputFormField({
Key key, Key key,
......
...@@ -6,8 +6,15 @@ import 'package:flutter/foundation.dart'; ...@@ -6,8 +6,15 @@ import 'package:flutter/foundation.dart';
import 'framework.dart'; import 'framework.dart';
/// A container for grouping together multiple form field widgets (e.g. /// An optional container for grouping together multiple form field widgets
/// [Input] widgets). /// (e.g. [Input] 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].
class Form extends StatefulWidget { class Form extends StatefulWidget {
/// Creates a container for form fields. /// Creates a container for form fields.
/// ///
...@@ -141,6 +148,11 @@ typedef Widget FormFieldBuilder<T>(FormFieldState<T> field); ...@@ -141,6 +148,11 @@ typedef Widget FormFieldBuilder<T>(FormFieldState<T> field);
/// Use a [GlobalKey] with [FormField] if you want to retrieve its current /// Use a [GlobalKey] with [FormField] if you want to retrieve its current
/// state, for example if you want one form field to depend on another. /// state, for example if you want one form field to depend on another.
/// ///
/// A [Form] ancestor is not required. The [Form] simply makes it easier to
/// save, reset, or validate multiple fields at once. To use without a [Form],
/// pass a [GlobalKey] to the constructor and use [GlobalKey.currentState] to
/// save or reset the form field.
///
/// See also: [Form], [InputFormField] /// See also: [Form], [InputFormField]
class FormField<T> extends StatefulWidget { class FormField<T> extends StatefulWidget {
FormField({ FormField({
...@@ -173,6 +185,8 @@ class FormField<T> extends StatefulWidget { ...@@ -173,6 +185,8 @@ class FormField<T> extends StatefulWidget {
FormFieldState<T> createState() => new FormFieldState<T>(); FormFieldState<T> createState() => new FormFieldState<T>();
} }
/// The current state of a [FormField]. Passed to the [FormFieldBuilder] method
/// for use in constructing the form field's widget.
class FormFieldState<T> extends State<FormField<T>> { class FormFieldState<T> extends State<FormField<T>> {
T _value; T _value;
String _errorText; String _errorText;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment