Skip to content

RawAutocomplete: Doc on onSelected seems wrong about TextEditingController listeners #130187

@chrisbobbe

Description

@chrisbobbe

Is there an existing issue for this?

Steps to reproduce

This is the dartdoc on [RawAutocomplete.onSelected]:

  /// {@template flutter.widgets.RawAutocomplete.onSelected}
  /// Called when an option is selected by the user.
  ///
  /// Any [TextEditingController] listeners will not be called when the user
  /// selects an option, even though the field will update with the selected
  /// value, so use this to be informed of selection.
  /// {@endtemplate}
  final AutocompleteOnSelected<T>? onSelected;

That second paragraph—

  /// Any [TextEditingController] listeners will not be called when the user
  /// selects an option, even though the field will update with the selected
  /// value, so use this to be informed of selection.

—doesn't seem quite right. When RawAutocomplete registers a new option selection (i.e., when it calls its _select method with a new nextSelection), this code is run:

    _textEditingController.value = TextEditingValue(
      selection: TextSelection.collapsed(offset: selectionString.length),
      text: selectionString,
    );

Since [TextEditingController] extends ValueNotifier<…>, it will indeed notify any listeners that have been added. This can be seen in my code sample, copy-pasted below:

  1. Run the code sample. It has a stateful widget holding a _textEditingController, which it passes to a RawAutocomplete. That controller has a listener on it that prints "called $index".
  2. Tap the text field to focus it.
  3. (See called 0 printed, because focusing caused _textEditingController.value to change; it now has a cursor at 0.)
  4. Tap one of the autocomplete options.
  5. See called 1 printed, despite the doc saying that no [TextEditingController] listeners would be called.

As a fix, I think that whole paragraph in the doc can be removed. I have an idea what might have led to adding that paragraph, and a further improvement to the docs with that in mind: #130187 (comment).

Expected results

I think the doc should not say

  /// Any [TextEditingController] listeners will not be called when the user
  /// selects an option, even though the field will update with the selected
  /// value

Actual results

The doc does say that.

Code sample

Code sample
import 'package:flutter/material.dart';

void main() => runApp(const AutocompleteExampleApp());

class AutocompleteExampleApp extends StatelessWidget {
  const AutocompleteExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: AutocompleteExample())));
  }
}

class AutocompleteExample extends StatefulWidget {
  const AutocompleteExample({super.key});

  @override
  AutocompleteExampleState createState() => AutocompleteExampleState();
}

class AutocompleteExampleState extends State<AutocompleteExample> {
  final TextEditingController _textEditingController = TextEditingController();
  final FocusNode _focusNode = FocusNode();
  int index = 0;

  @override
  void initState() {
    super.initState();
    _textEditingController.addListener(() {
      print('called $index');
      index++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return RawAutocomplete<String>(
      textEditingController: _textEditingController,
      focusNode: _focusNode,
      optionsBuilder: (TextEditingValue textEditingValue) => ['aardvark', 'bobcat', 'chameleon'],
      fieldViewBuilder: (BuildContext context, TextEditingController textEditingController, FocusNode focusNode, VoidCallback onFieldSubmitted) => TextField(
        controller: textEditingController,
        focusNode: focusNode),
      optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<String> onSelected, Iterable<String> options) => Align(
        alignment: Alignment.topLeft,
        child: Material(
          child: ListView.builder(
            itemCount: options.length,
            itemBuilder: (BuildContext context, int index) {
              final String option = options.elementAt(index);
              return GestureDetector(
                onTap: () {
                  onSelected(option);
                },
                child: ListTile(
                  title: Text(option)));
            }))));
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs

(No errors expected or observed.)

Flutter Doctor output

Doctor output
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel main, 3.12.0-15.0.pre.39, on macOS 13.4.1 22F82 darwin-x64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] VS Code (version 1.79.2)
[✓] Connected device (3 available)
    ! Error: Chris’s Apple Watch has recently restarted. To use Chris’s Apple Watch with Xcode, unlock it and its
      companion iPhone (code 19)
[✓] Network resources

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: text inputEntering text in a text field or keyboard related problemsd: api docsIssues with https://api.flutter.dev/found in release: 3.10Found to occur in 3.10found in release: 3.12Found to occur in 3.12frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions