skip to Main Content

I have a problem to keep the value of my Texfield field when I return to one of my pages of my form.
I’m using the components PageController with PageView.

I wrote a simple exemple to explain.
It’s not optimized but it’s enough to explain my problem.

I have 3 pages. The first two pages are a form containing a Textfield component.
The last page is a summary.
The appBar and bottomNavigationBar components are cross-functional components.

enter image description here

Use case of the problem :

When I click on the button "Next" it works, the value on my differents fields are saved in a object "FormData".
BUT, my problem is, when I click on previous button.
I lose the value I entered in my field although it is still in my formData object

Here the body :

@override
    Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('PageView Example'),
          ),
          body: Column(
            children: [
              linearProgressIndicator(),
              Expanded(
                child: PageView(
                  controller: _pageController,
                  children: <Widget>[
                    FormPage1(),
                    FormPage2(),
                    SummaryPage(),
                  ],
                ),
              ),
            ],
          ),
          bottomNavigationBar: bottomBarWidget(),
        );
      }

The code of the buttons :

void _navigateToNextPage() {
    if (_pageController.page!.round() < 2) {
      _pageController.nextPage(
          duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
    }
  }

  void _navigateToPreviousPage() {
    if (_pageController.page!.round() > 0) {
      _pageController.previousPage(
          duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
    }
  }

The code of FormPage

class FormData extends ChangeNotifier {
  String? field1;
  String? field2;
}

class FormPage1 extends StatelessWidget {
  TextEditingController controllerTitle = TextEditingController();

  @override
  Widget build(BuildContext context) {
    var formData = Provider.of<FormData>(context);
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Page 1 - Form'),
            TextField(
              controller: controllerTitle,
              onChanged: (value) {
                formData.field1 = value;
              },
              decoration: InputDecoration(labelText: 'Field 1'),
            ),
          ],
        ),
      ),
    );
  }
}

The SummaryPage

class SummaryPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var formData = Provider.of<FormData>(context);
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('Summary Page'),
          Text('Field 1: ${formData.field1 ?? ""}'),
          Text('Field 2: ${formData.field2 ?? ""}'),
        ],
      ),
    );
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    Adding the property "initialValue:" I get an ERROR :

    enter image description here

    So I added in the first component my formData : var formData = Provider.of(context); I don't know if it's a right way to do it but it's work.

    @override
      Widget build(BuildContext context) {
        var _formData = Provider.of<FormData>(context);
        return Scaffold(
          appBar: AppBar(
            title: Text('PageView Example'),
          ),
          body: Column(
            children: [
              linearProgressIndicator(),
              Expanded(
                child: PageView(
                  controller: _pageController,
                  children: <Widget>[
                    FormPage1(formData: _formData),
                    FormPage2(),
                    SummaryPage(),
                  ],
                ),
              ),
            ],
          ),
          bottomNavigationBar: bottomBarWidget(),
        );
      }
    
    
    
    class _FormPage1State extends State<FormPage1> {
          TextEditingController controllerTitle = TextEditingController();
        
          @override
          void initState() {
              setState(() {
                if (widget.formData.field1 != null) {
                  controllerTitle.text = widget.formData.field1!;
                }
              });
            super.initState();
          }
        
          @override
          Widget build(BuildContext context) {
            var formData = Provider.of<FormData>(context);
        
            return Scaffold(
              body: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text('Page 1 - Form'),
                    TextFormField(
                      controller: controllerTitle,
                      onChanged: (value) {
                        formData.field1 = value;
                      },
                      decoration: InputDecoration(labelText: 'Field 1'),
                    ),
                  ],
                ),
              ),
            );
          }
        }
    

  2. try to initialize TextFormField‘s Controller with an empty string and set the initialValue of the form field to controller.text.

    ex:

    class TTF extends StatelessWidget{
    
    var controller = TextEditingController(text: '');
    
    Widget build(BuildContext context){
    return TextFormField(
    controller:controller,
    initialValue: controller.text,
    );
    }
    
    } 
    

    that rebuilds your pages on call without losing previously entered data.

    note: the above code is not a customized implementation of text field, mainly it’s a stateful, but it’s a short way to explain my opinion.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search