From 9f35f6c3a69263266d4db5acfb3eb95fac08e7bd Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Wed, 27 Feb 2019 17:24:06 -0800 Subject: [PATCH] Add warnings and an example to the TextEditingController docs (#28604) --- .../lib/src/widgets/editable_text.dart | 62 ++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 0bdfe56e23e..9766030600f 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -62,6 +62,50 @@ const int _kObscureShowLatestCharCursorTicks = 3; /// text field. If you build a text field with a controller that already has /// [text], the text field will use that text as its initial value. /// +/// The [text] or [selection] properties can be set from within a listener +/// added to this controller. If both properties need to be changed then the +/// controller's [value] should be set instead. +/// +/// {@tool snippet --template=stateful_widget_material} +/// This example creates a [TextField] with a [TextEditingController] whose +/// change listener forces the entered text to be lower case and keeps the +/// cursor at the end of the input. +/// +/// ```dart +/// final _controller = TextEditingController(); +/// +/// void initState() { +/// _controller.addListener(() { +/// final text = _controller.text.toLowerCase(); +/// _controller.value = _controller.value.copyWith( +/// text: text, +/// selection: TextSelection(baseOffset: text.length, extentOffset: text.length), +/// composing: TextRange.empty, +/// ); +/// }); +/// super.initState(); +/// } +/// +/// void dispose() { +/// _controller.dispose(); +/// super.dispose(); +/// } +/// +/// Widget build(BuildContext context) { +/// return Scaffold( +/// body: Container( +/// alignment: Alignment.center, +/// padding: const EdgeInsets.all(6), +/// child: TextFormField( +/// controller: _controller, +/// decoration: InputDecoration(border: OutlineInputBorder()), +/// ), +/// ), +/// ); +/// } +/// ``` +/// {@end-tool} +/// /// See also: /// /// * [TextField], which is a Material Design text field that can be controlled @@ -89,10 +133,17 @@ class TextEditingController extends ValueNotifier { /// that they need to update (it calls [notifyListeners]). For this reason, /// this value should only be set between frames, e.g. in response to user /// actions, not during the build, layout, or paint phases. + /// + /// This property can be set from a listener added to this + /// [TextEditingController]; however, one should not also set [selection] + /// in a separate statement. To change both the [text] and the [selection] + /// change the controller's [value]. set text(String newText) { - value = value.copyWith(text: newText, - selection: const TextSelection.collapsed(offset: -1), - composing: TextRange.empty); + value = value.copyWith( + text: newText, + selection: const TextSelection.collapsed(offset: -1), + composing: TextRange.empty + ); } /// The currently selected [text]. @@ -104,6 +155,11 @@ class TextEditingController extends ValueNotifier { /// that they need to update (it calls [notifyListeners]). For this reason, /// this value should only be set between frames, e.g. in response to user /// actions, not during the build, layout, or paint phases. + /// + /// This property can be set from a listener added to this + /// [TextEditingController]; however, one should not also set [text] + /// in a separate statement. To change both the [text] and the [selection] + /// change the controller's [value]. set selection(TextSelection newSelection) { if (newSelection.start > text.length || newSelection.end > text.length) throw FlutterError('invalid text selection: $newSelection');