Unverified Commit 9a3b6c3b authored by Hans Muller's avatar Hans Muller Committed by GitHub

Text form field initial value (#15484)

parent 7667db63
...@@ -19,9 +19,15 @@ import 'theme.dart'; ...@@ -19,9 +19,15 @@ import 'theme.dart';
/// pass a [GlobalKey] to the constructor and use [GlobalKey.currentState] to /// pass a [GlobalKey] to the constructor and use [GlobalKey.currentState] to
/// save or reset the form field. /// save or reset the form field.
/// ///
/// When a [controller] is specified, it can be used to control the text being /// When a [controller] is specified, its [TextEditingController.text]
/// edited. Its content will be overwritten by [initialValue] (which defaults /// defines the [initialValue]. If this [FormField] is part of a scrolling
/// to the empty string) on creation and when [reset] is called. /// container that lazily constructs its children, like a [ListView] or a
/// [CustomScrollView], then a [controller] should be specified.
/// The controller's lifetime should be managed by a stateful widget ancestor
/// of the scrolling container.
///
/// If a [controller] is not specified, [initialValue] can be used to give
/// the automatically generated controller an initial value.
/// ///
/// For a documentation about the various parameters, see [TextField]. /// For a documentation about the various parameters, see [TextField].
/// ///
...@@ -35,16 +41,17 @@ import 'theme.dart'; ...@@ -35,16 +41,17 @@ import 'theme.dart';
class TextFormField extends FormField<String> { class TextFormField extends FormField<String> {
/// Creates a [FormField] that contains a [TextField]. /// Creates a [FormField] that contains a [TextField].
/// ///
/// When a [controller] is specified, it can be used to control the text /// When a [controller] is specified, [initialValue] must be null (the
/// being edited. Its content will be overwritten by [initialValue] (which /// default). If [controller] is null, then a [TextEditingController]
/// defaults to the empty string) on creation and when [reset] is called. /// will be constructed automatically and its `text` will be initialized
/// to [initalValue] or the empty string.
/// ///
/// For documentation about the various parameters, see the [TextField] class /// For documentation about the various parameters, see the [TextField] class
/// and [new TextField], the constructor. /// and [new TextField], the constructor.
TextFormField({ TextFormField({
Key key, Key key,
this.controller, this.controller,
String initialValue: '', String initialValue,
FocusNode focusNode, FocusNode focusNode,
InputDecoration decoration: const InputDecoration(), InputDecoration decoration: const InputDecoration(),
TextInputType keyboardType: TextInputType.text, TextInputType keyboardType: TextInputType.text,
...@@ -58,7 +65,7 @@ class TextFormField extends FormField<String> { ...@@ -58,7 +65,7 @@ class TextFormField extends FormField<String> {
FormFieldSetter<String> onSaved, FormFieldSetter<String> onSaved,
FormFieldValidator<String> validator, FormFieldValidator<String> validator,
List<TextInputFormatter> inputFormatters, List<TextInputFormatter> inputFormatters,
}) : assert(initialValue != null), }) : assert(initialValue == null || controller == null),
assert(keyboardType != null), assert(keyboardType != null),
assert(textAlign != null), assert(textAlign != null),
assert(autofocus != null), assert(autofocus != null),
...@@ -67,7 +74,7 @@ class TextFormField extends FormField<String> { ...@@ -67,7 +74,7 @@ class TextFormField extends FormField<String> {
assert(maxLines == null || maxLines > 0), assert(maxLines == null || maxLines > 0),
super( super(
key: key, key: key,
initialValue: initialValue, initialValue: controller != null ? controller.text : (initialValue ?? ''),
onSaved: onSaved, onSaved: onSaved,
validator: validator, validator: validator,
builder: (FormFieldState<String> field) { builder: (FormFieldState<String> field) {
...@@ -94,7 +101,8 @@ class TextFormField extends FormField<String> { ...@@ -94,7 +101,8 @@ class TextFormField extends FormField<String> {
/// Controls the text being edited. /// Controls the text being edited.
/// ///
/// If null, this widget will create its own [TextEditingController]. /// If null, this widget will create its own [TextEditingController] and
/// initialize its [TextEditingController.text] with [initialValue].
final TextEditingController controller; final TextEditingController controller;
@override @override
...@@ -115,7 +123,6 @@ class _TextFormFieldState extends FormFieldState<String> { ...@@ -115,7 +123,6 @@ class _TextFormFieldState extends FormFieldState<String> {
if (widget.controller == null) { if (widget.controller == null) {
_controller = new TextEditingController(text: widget.initialValue); _controller = new TextEditingController(text: widget.initialValue);
} else { } else {
widget.controller.text = widget.initialValue;
widget.controller.addListener(_handleControllerChanged); widget.controller.addListener(_handleControllerChanged);
} }
} }
......
...@@ -204,8 +204,8 @@ void main() { ...@@ -204,8 +204,8 @@ void main() {
expect(editableText.widget.controller.text, equals('world')); expect(editableText.widget.controller.text, equals('world'));
}); });
testWidgets('Provide initial value to input when controller is specified', (WidgetTester tester) async { testWidgets('Controller defines initial value', (WidgetTester tester) async {
final TextEditingController controller = new TextEditingController(); final TextEditingController controller = new TextEditingController(text: 'hello');
const String initialValue = 'hello'; const String initialValue = 'hello';
final GlobalKey<FormFieldState<String>> inputKey = new GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> inputKey = new GlobalKey<FormFieldState<String>>();
...@@ -217,7 +217,6 @@ void main() { ...@@ -217,7 +217,6 @@ void main() {
child: new Form( child: new Form(
child: new TextFormField( child: new TextFormField(
key: inputKey, key: inputKey,
initialValue: 'hello',
controller: controller, controller: controller,
), ),
), ),
...@@ -251,7 +250,6 @@ void main() { ...@@ -251,7 +250,6 @@ void main() {
final GlobalKey<FormState> formKey = new GlobalKey<FormState>(); final GlobalKey<FormState> formKey = new GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> inputKey = new GlobalKey<FormFieldState<String>>(); final GlobalKey<FormFieldState<String>> inputKey = new GlobalKey<FormFieldState<String>>();
final TextEditingController controller = new TextEditingController(text: 'Plover'); final TextEditingController controller = new TextEditingController(text: 'Plover');
const String initialValue = 'Plugh';
Widget builder() { Widget builder() {
return new Directionality( return new Directionality(
...@@ -263,7 +261,7 @@ void main() { ...@@ -263,7 +261,7 @@ void main() {
child: new TextFormField( child: new TextFormField(
key: inputKey, key: inputKey,
controller: controller, controller: controller,
initialValue: initialValue, // initialValue is 'Plover'
), ),
), ),
), ),
...@@ -284,9 +282,9 @@ void main() { ...@@ -284,9 +282,9 @@ void main() {
// verify value resets to initialValue on reset. // verify value resets to initialValue on reset.
formKey.currentState.reset(); formKey.currentState.reset();
await tester.idle(); await tester.idle();
expect(inputKey.currentState.value, equals(initialValue)); expect(inputKey.currentState.value, equals('Plover'));
expect(editableText.widget.controller.text, equals(initialValue)); expect(editableText.widget.controller.text, equals('Plover'));
expect(controller.text, equals(initialValue)); expect(controller.text, equals('Plover'));
}); });
testWidgets('TextEditingController updates to/from form field value', (WidgetTester tester) async { testWidgets('TextEditingController updates to/from form field value', (WidgetTester tester) async {
......
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