Skip to content

Commit 86e7cd4

Browse files
Add migration guide for text field focus node change (#6407)
* Add migration guide for text field focus node change * Update editable-text-focus-attachment.md * Update editable-text-focus-attachment.md * Update landed version * Apply suggestions from code review Co-authored-by: Shams Zakhour (ignore Sfshaza) <44418985+sfshaza2@users.noreply.github.com> * Fix master api link Co-authored-by: Shams Zakhour (ignore Sfshaza) <44418985+sfshaza2@users.noreply.github.com>
1 parent e26c51c commit 86e7cd4

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: TextField FocusNode attach location change
3+
description: EditableText.focusNode is no longer attached to EditableTextState's BuildContext
4+
---
5+
6+
## Summary
7+
8+
`EditableText.focusNode` is now attached to a dedicated `Focus` widget below
9+
`EditableText`.
10+
11+
## Context
12+
13+
A text input field widget (`TextField`, for example) typically owns a `FocusNode`.
14+
When that `FocusNode` is the primary focus of the app, events (such as key presses)
15+
are sent to the `BuildContext` to which the `FocusNode` is attached.
16+
17+
The `FocusNode` also plays a roll in shortcut handling: The `Shortcuts` widget
18+
translates key sequences into an `Intent`, and tries to find the first suitable
19+
handler for that `Intent` starting from the `BuildContext` to which the `FocusNode`
20+
is attached, to the root of the widget tree. This means an `Actions` widget (that provides
21+
handlers for different `Intent`s) won't be able to handle any shortcut `Intent`s
22+
when the `BuildContext` that has the primary focus is above it in the tree.
23+
24+
Previously for `EditableText`, the `FocusNode` was attached to the `BuildContext`
25+
of `EditableTextState`. Any `Actions` widgets defined in `EditableTextState` (which
26+
will be inflated below the `BuildContext` of the `EditableTextState`) couldn't
27+
handle shortcuts even when that `EditableText` was focused, for the reason stated
28+
above.
29+
30+
## Description of change
31+
32+
`EditableTextState` now creates a dedicated `Focus` widget to host `EditableText.focusNode`.
33+
This allows `EditableTextState`s to define handlers for shortcut `Intent`s. For
34+
instance, `EditableText` now has a handler that handles the "deleteCharacter" intent
35+
when the <kbd>DEL<kbd> key is pressed.
36+
37+
This change does not involve any public API changes but breaks codebases relying on
38+
that particular implementation detail to tell if a `FocusNode` is associated with a
39+
text input field.
40+
41+
This change does not break any builds but can introduce runtime issues, or
42+
cause existing tests to fail.
43+
44+
## Migration guide
45+
46+
The `EditableText` widget takes a `FocusNode` as a paramter, which was
47+
previously attached to its `EditableText`'s `BuildContext`. If you are relying
48+
on runtime typecheck to find out if a `FocusNode` is attached to a text input
49+
field or a selectable text field like so:
50+
51+
- `focusNode.context.widget is EditableText`
52+
- `(focusNode.context as StatefulElement).state as EditableTextState`
53+
54+
Then please read on and consider following the migration steps to avoid breakages.
55+
56+
If you're not sure whether a codebase needs migration, search for `is EditableText`,
57+
`as EditableText`, `is EditableTextState`, and `as EditableTextState` and verify if
58+
any of the search results are doing a typecheck or typecast on a `FocusNode.context`.
59+
If so, then migration is needed.
60+
61+
To avoid performing a typecheck, or downcasting the `BuildContext` associated with the
62+
`FocusNode` of interest, and depending on the actual capabilities the codebase is
63+
trying to invoke from the given `FocusNode`, fire an `Intent` from that
64+
`BuildContext`. For instance, if you wish to update the text of the currently focused
65+
`TextField` to a specific value, see the following example:
66+
67+
Code before migration:
68+
69+
<!-- skip -->
70+
```dart
71+
final Widget? focusedWidget = primaryFocus?.context?.widget;
72+
if (focusedWidget is EditableText) {
73+
widget.controller.text = 'Updated Text';
74+
}
75+
```
76+
77+
Code after migration:
78+
79+
<!-- skip -->
80+
```dart
81+
final BuildContext? focusedContext = primaryFocus?.context;
82+
if (focusedContext != null) {
83+
Actions.maybeInvoke(focusedContext, ReplaceTextIntent('UpdatedText'));
84+
}
85+
```
86+
87+
For a comprehensive list of `Intent`s supported by the `EditableText` widget,
88+
refer to the documentation of the `EditableText` widget.
89+
90+
## Timeline
91+
92+
Landed in version: 2.6.0-12.0.pre<br>
93+
In stable release: not yet
94+
95+
## References
96+
97+
API documentation:
98+
99+
* [`EditableText`][]
100+
101+
Relevant PRs:
102+
103+
* [Move text editing Actions to EditableTextState][]
104+
105+
[`EditableText`]: {{site.master-api}}/flutter/widgets/EditableText-class.html
106+
[Move text editing Actions to EditableTextState]: {{site.github}}/flutter/flutter/pull/90684
107+

0 commit comments

Comments
 (0)