felixmccuaig / flutter-autocomplete-textfield

An autocomplete Textfield for flutter
MIT License
181 stars 131 forks source link

Dialog wouldn't dismiss after submitted #35

Open JohnPang1204 opened 5 years ago

JohnPang1204 commented 5 years ago

Hi, felixlucien. That is not working anymore after i upgraded flutter version. It's able to prompt dialog if user input relevant to predefined list. but dialog wouldn't dismiss anymore after submitted. I attached error msg below. Thank you for your helping.

I/flutter ( 4443): ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════ I/flutter ( 4443): The following NoSuchMethodError was thrown while dispatching notifications for FocusNode: I/flutter ( 4443): The method 'call' was called on null. I/flutter ( 4443): Receiver: null I/flutter ( 4443): Tried calling: call(true) I/flutter ( 4443): I/flutter ( 4443): When the exception was thrown, this was the stack: I/flutter ( 4443): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5) I/flutter ( 4443): #1 new AutoCompleteTextFieldState. (package:autocomplete_textfield/autocomplete_textfield.dart:182:4) I/flutter ( 4443): #2 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:206:21) I/flutter ( 4443): #3 FocusNode._notify (package:flutter/src/widgets/focus_manager.dart:103:5) I/flutter ( 4443): #4 FocusManager._update (package:flutter/src/widgets/focus_manager.dart:474:20) I/flutter ( 4443): (elided 10 frames from package dart:async) I/flutter ( 4443): I/flutter ( 4443): The FocusNode sending notification was: I/flutter ( 4443): FocusNode#06da5(FOCUSED) I/flutter ( 4443): ════════════════════════════════════════════════════════════════════════════════════════════════════ I/flutter ( 4443): 1 W/IInputConnectionWrapper( 4443): getTextBeforeCursor on inactive InputConnection I/flutter ( 4443): Another exception was thrown: NoSuchMethodError: The method 'call' was called on null.

mayurprajapati commented 5 years ago

I got the same error.

ahaboubi commented 5 years ago

Same here

rmathias86 commented 5 years ago

I'm facing the same issue here.

asrinagesh commented 5 years ago

Has anyone found a solution?

rmathias86 commented 5 years ago

Unfortunately, I haven't found a solution yet. I've decided to use this one https://pub.dev/documentation/flutter_typeahead_plugin/latest/

LordLaser commented 5 years ago

I had to add this to the AutoCompleteTextField properties even though it's not marked as required:

onFocusChanged: (hasFocus) {},

Karlheinzniebuhr commented 5 years ago

I have the same issue, the suggestions won't disappear when selecting one. But no error is shown in the console. This issue happens with v 1.6.4 and 1.6.6

aleaforny commented 5 years ago

I have the same issue, the suggestions won't disappear when selecting one. But no error is shown in the console. This issue happens with v 1.6.4 and 1.6.6

Have you tried to add the property onFocusChanged: (hasFocus) {} to your widget ?

Karlheinzniebuhr commented 5 years ago

I have the same issue, the suggestions won't disappear when selecting one. But no error is shown in the console. This issue happens with v 1.6.4 and 1.6.6

Have you tried to add the property onFocusChanged: (hasFocus) {} to your widget ?

That solved the issue, thanks!

felixmccuaig commented 5 years ago

I'll look into it. Thanks.

felixmccuaig commented 5 years ago

I'm going to need a little bit more information to fix this issue, would you mind supplying some code which causes this error?

Karlheinzniebuhr commented 5 years ago

this is my code which was solved once I added hasFocus()

` asignSearchTextField = AutoCompleteTextField( //style: new TextStyle(color: Colors.black, fontSize: 15.0), decoration: InputDecoration( // suffixIcon: Container( // width: 85.0, // height: 60.0, // ), filled: false, //labelText: 'Asignar a', hintText: 'Asignar a', //hintStyle: TextStyle(color: Colors.black38),

      errorText: _validateAssignee ? 'Debe asignar a alguien' : null,
      prefixIcon: Icon(Icons.person),
    ),
    itemSubmitted: (item) {
      print('itemSubmitted');
      setState(() {
        _task.assignee_id = item.id;
        asignSearchTextField.textField.controller.text = item.username;
      });
    },
    onFocusChanged: (hasFocus) {},
    clearOnSubmit: false,
    submitOnSuggestionTap: true,
    key: key,
    suggestions: UsersViewModel.users ?? [],
    itemBuilder: (context, item) {
      print('itemBuilder');
      return Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Text(
            item.username,
            style: TextStyle(fontSize: 16.0),
          ),
          Padding(
            padding: EdgeInsets.all(15.0),
          ),
          Text(
            item.email,
            style: TextStyle(fontSize: 16.0),
          )
        ],
      );
    },
    minLength: 0,
    itemSorter: (a, b) {
      print('itemSorter');
      return a.username.compareTo(b.username);
    },
    itemFilter: (item, query) {
      print('itemFilter');
      return item.username.toLowerCase().startsWith(query.toLowerCase());
    });`
felixmccuaig commented 5 years ago

Thanks, however, I'm still not really understanding the dialog part. Is the TextField inside a dialog? Is the submit action creating/closing a dialog?

Karlheinzniebuhr commented 5 years ago

Before (dialog won't dismiss)

before

After using onFocusChanged: (hasFocus) {},

after

banfger commented 5 years ago

onFocusChanged: (hasFocus) {} did nothing for me. But looking into the source code, I could solve it.

In the updateOverlay function selecting the text does not result in an update, so I changed it to this:

onTap: () {
   setState(() {
      if (submitOnSuggestionTap) {
         String newText = suggestion.toString();
         textField.controller.text = newText;
         textField.focusNode.unfocus();
         itemSubmitted(suggestion);
         if (clearOnSubmit) {
            clear();
         }
         else{
            updateOverlay();
         }
     }
     else {
        String newText = suggestion.toString();
        textField.controller.text = newText;
        textChanged(newText);
        updateOverlay();
    }
   });
}

Now after selecting a suggestion the dialog disappears. But if you click in the textfield again, the new suggestions are the same as the ones that were suggested at the time you selected the current value. What should appear are the suggestions for the submitted value, so itself. It is solved if I add currentText = newText like this:

onTap: () {
   setState(() {
      if (submitOnSuggestionTap) {
         String newText = suggestion.toString();
         textField.controller.text = newText;
         textField.focusNode.unfocus();
         itemSubmitted(suggestion);
         if (clearOnSubmit) {
            clear();
         }
         else{
            currentText = newText;
            updateOverlay();
         }
     }
     else {
        String newText = suggestion.toString();
        textField.controller.text = newText;
        currentText = newText;
        textChanged(newText);
        updateOverlay();
    }
   });
}

And lastly, somehow after a decoration update the textfield loses it's focusNode and it's listener. I simply changed the updateDecoration function by adding the listener again if the focusNode null, and it is good for me.

setState(() {
      if(focusNode == null){
        focusNode = new FocusNode()..addListener(() {
          if (onFocusChanged != null) {
            onFocusChanged(textField.focusNode.hasFocus);
          }
          if (!textField.focusNode.hasFocus) {
            filteredSuggestions = [];
            updateOverlay();
          }
          else if (!(currentText == "" || currentText == null)) {
            updateOverlay(currentText);
          }
        });
      }

      textField = new TextField(
        inputFormatters: this.inputFormatters,
        textCapitalization: this.textCapitalization,
        decoration: this.decoration,
        style: this.style,
        keyboardType: this.keyboardType,
        focusNode: focusNode ?? ?? FocusNode(),
        controller: controller ?? new TextEditingController(),
        textInputAction: this.textInputAction,
        onChanged: (newText) {
          currentText = newText;
          updateOverlay(newText);

          if (textChanged != null) {
            textChanged(newText);
          }
        },
        onTap: () {
          updateOverlay(currentText);
        },
        onSubmitted: (submittedText) =>
            triggerSubmitted(submittedText: submittedText),
      );
    });