Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flutter - update TextField/TextEditingController via state (provider/consumer)

Tags:

flutter

dart

i have a TextField on a "page". i have a TextEditingController hooked to it. I can successfully set the value of the TextField via something easy like:

usernameController.text = '1234';

however, i need to be able to change this field from a child page. the use case is a login form where the user logs out from inside the app. when i return to the login page, i want the username/password to be wiped out/deleted. right now, the values are still there (showing whatever is currently in usernameController.text)

overall, i'm managing state via Provider. i can set and retrieve/display state in other places in my app with no problem. the issue becomes that the controller is setup via dart code in initState(). it is not part of a widget that gets rebuilt.

i can setup the TextField widget within a consumer. the builder gets called when state is updated in the child page (confirmed with the debug print statement) but the widget itself does not reflect the new value of the state (it still has the old username and it is not blanked out).

                            Consumer<myAppState>(
                          builder: (context, appState, child) {
                            print("in builder for consumer: ");
                            print(appState.username);
                            return Container(
                                width: 200,
                                child: TextField(
                                  controller: usernameController,
                                  onChanged: (value) => _saveUsername(value),
                                  decoration: InputDecoration(
                                    hintText: 'Username',
                                    prefixIcon: Icon(Icons.account_circle),
                                  ),
                                ));
                          }),

I've tried replacing

usernameController.text = '1234';

with:

usernameController.text = Provider.of<myAppState>(context, listen: true).username;

but that does not seem to work.

it seems this "non-pure" widget (because of the controller being handled programatically) doesn't sit pretty within the Consumer model which wants to redraw widgets.

anyone have any thoughts?

thanks!

like image 646
user3249281 Avatar asked Oct 09 '19 15:10

user3249281


1 Answers

One possible way is to check make a check in the builder if the value in state and controller matches and sync them.

Example:

Consumer<myAppState>(
  builder: (context, appState, child) {
    print("in builder for consumer: ");
    print(appState.username);
    if (usernameController.text != appState.username) { // Or check if appState.username != null or what ever your use case is.
      usernameController.text = appState.username ?? '';
    }
    return Container(
      width: 200,
      child: TextField(
        controller: usernameController,
        onChanged: (value) => _saveUsername(value),
        decoration: InputDecoration(
          hintText: 'Username',
          prefixIcon: Icon(Icons.account_circle),
        ),
      ),
    );
  },
)

Hope that helps!

like image 64
Hemanth Raj Avatar answered Oct 18 '22 20:10

Hemanth Raj