Search code examples
flutterstatebloc

What is the correct approach to assign initial values to TextEditingController from the database?


I have a user profile view which is Statefull Widget. Inside I have a TextFormField with the username which I would like the user to be able to change, but also it should display the existing username from the database. So basicly on widget initialize I would like to assign value of username to TextEditingController just once (otherwise it would overwrite value on widget reload).

Here is what I already did (and it works how I want) but it seems a little bit stupid to do this the way I did it. I just started learning flutter and I wonder what is a better way to do that.

I created TextController for userName field and boolean value called "_valuesAssigned":

class _UserProfileViewState extends State<UserProfileView> {
  late final TextEditingController _userNameTextController;
  late bool _valuesAssigned;

  @override
  void initState() {
    _userNameTextController = TextEditingController();
    _valuesAssigned = false;
    super.initState();
  }

  @override
  void dispose() {
    _userNameTextController.dispose();
    super.dispose();
  }

Next I have a BlocConsumer where I assign value from database to TextController and change _valuesAssigned to make sure the code will run once and won't overwrite user changes on widget rebuild.

@override
  Widget build(BuildContext context) {
    return BlocConsumer<AppBloc, AppState>(
      listener: (context, state) {
         // Code that doesn't matter
      },
      builder: (context, state) {
        if (state is UsersStateEditingUser) {
          if (!_valuesAssigned) {
            _userNameTextController.text = state.user?.userName;
            valuesAssigned = true;
          }
          return WillPopScope(
            onWillPop: () async {
              // Code that doesn't matter
            },
            child: Scaffold(
              appBar: AppBar(
                // Code that doesn't matter
                ),
              ),
              body: Scrollbar(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    // Code that doesn't matter
                  ),
                ),
              ),
            ),
          );
        } else {
          return const CircularProgressIndicator.adaptive();
        }
      },
    );
  }

Solution

  • I would read the database with the bloc and feed some progress indicator in the view until then. Once the user is read, emit it to the view. When the user enters a different name, send an event with the new name. The controller then always receives its value from the bloc state