Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VM -> widget data transfer: am I doing it right? #17

Closed
kentcb opened this issue Mar 7, 2018 · 3 comments
Closed

VM -> widget data transfer: am I doing it right? #17

kentcb opened this issue Mar 7, 2018 · 3 comments

Comments

@kentcb
Copy link

kentcb commented Mar 7, 2018

Hi,

There's something I've found myself doing in each of my views, and I can't help but think it's more complicated than it should be, so I just wanted to check in to see how I should be handling this.

The scenario is simply that I want to transfer data from the VM to the view for a TextField that has a controller. The reasons I might need to do this include:

  1. The view has just been created and it needs to reflect data in the VM that has been loaded.
  2. Reducers have decided that a particular value should change. That change needs to propagate to the view (via the VM).

As a simple example, imagine a login page. When login fails, the reducer resets the password back to empty (or null). That should of course be reflected in the view. However, I don't see a way to ensure this without manually applying the value to the TextEditingController.

Manually transferring the values isn't so bad, except that it quickly gets complicated because I need to take selection into account. Currently my helper method looks like this:

void _updateText(TextEditingController controller, String text) {
  text = text ?? "";
  var selection = controller.selection;
  controller.text = text;

  if (selection.start > text.length || selection.end > text.length) {
    return;
  }

  controller.selection = selection;
}

I call this at the start of my build method for each TextEditingController, passing in the value provided by the VM. It's all a bit awkward, so I feel like I'm missing something obvious here.

Any thoughts?

@brianegan
Copy link
Owner

Heya @kentcb :) Great question, as always! Let me see if I can tackle these:

1

The view has just been created and it needs to reflect data in the VM that has been loaded. -- In this case, I simply grab the strings I need from the store and pass it to my builder function. In the builder function, I use new TextFormField(initialValue: vm.initialValue);

2

I think the second case is the tricky one! Flutter is mostly reactive, but then has these imperative bits like TextEditingControllers and Navigators and it makes working with reactive patterns like Redux a bit harder. To be honest, I'm not sure how easy it would be with any pattern given the challenge with handling the selection :)

Lemme play around with a couple ideas and I'll see If I can come up with something a bit better! I can definitely understand your use case.

@kentcb
Copy link
Author

kentcb commented Mar 8, 2018

Yeah, the departure from the reactive approach has bitten me with RefreshIndicator as well, which I have lamented here.

It's also interesting to note that whilst TextFormField has an initialValue argument, TextField does not. There are some inconsistencies in flutter's API that I have found confusing, and this is one of them.

@brianegan
Copy link
Owner

Hey hey -- maybe should have closed this before now, but we now have the onWillChange callback in place. I think it should be the appropriate place to work with changes like this so you do not need to do some weird mutations inside the build method on each draw of the Widget, but only when the data changes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants