You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter多步骤表单切换后丢失输入值,如何修改代码保留状态?

解决多步骤表单输入值丢失问题

问题根源

表单切换时输入值丢失的核心原因:

  • 输入值未与全局状态绑定,页面销毁时数据未持久化
  • TextFormField未设置初始值,返回旧页面无法恢复内容
  • 步骤切换逻辑存在错误(如Back按钮跳转至错误步骤)

修改方案

1. 扩展全局状态类(Create.dart)

为每个步骤的表单字段单独添加存储属性,确保数据持久化:

class Create with ChangeNotifier {
  // 存储第一步表单内容
  String? question1Title;
  String? question1Description;
  
  // 存储第二步表单内容
  String? question2Title;
  String? question2Description;

  int activeIndex = 0;
  int totalIndex = 6;

  changeStep(int index) {
    activeIndex = index;
    notifyListeners();
  }

  // 可选:重置表单方法
  resetForm() {
    question1Title = null;
    question1Description = null;
    question2Title = null;
    question2Description = null;
    activeIndex = 0;
    notifyListeners();
  }
}

2. 修改第一步表单(form-question1.dart)

绑定全局状态,实现输入值的读取与同步:

class FormQuestion1 extends StatefulWidget {
  const FormQuestion1({super.key});
  static const routeName = '/form-question1';

  @override
  State<FormQuestion1> createState() => _FormQuestion1State();
}

class _FormQuestion1State extends State<FormQuestion1> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Consumer<Create>(builder: (context, modal, child) {
      return Form(
        key: _formKey,
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              TextFormField(
                // 从全局状态读取初始值
                initialValue: modal.question1Title,
                decoration: const InputDecoration(
                  labelText: 'title',
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value!.isEmpty)
                    return 'Please enter the title of question';
                },
                // 实时同步输入到全局状态
                onChanged: (value) {
                  modal.question1Title = value;
                  modal.notifyListeners();
                },
              ),
              const SizedBox(height: 16),
              TextFormField(
                initialValue: modal.question1Description,
                minLines: 3,
                maxLines: 5,
                decoration: const InputDecoration(
                  labelText: 'description',
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value!.isEmpty || value.length < 30) {
                    return 'Description must be longer';
                  }
                },
                onChanged: (value) {
                  modal.question1Description = value;
                  modal.notifyListeners();
                },
              ),
              Padding(
                padding: const EdgeInsets.all(10),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Expanded(
                      flex: 1,
                      child: ElevatedButton(
                        onPressed: modal.activeIndex > 0
                            ? () {
                                _formKey.currentState?.save();
                                modal.changeStep(modal.activeIndex - 1);
                              }
                            : null,
                        child: const Text('Back'),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 2,
                      child: ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState?.validate() ?? false) {
                            _formKey.currentState!.save();
                            // 此处添加提交逻辑
                            print('提交数据:${modal.question1Title}, ${modal.question1Description}');
                          }
                        }, 
                        child: const Text('Submit'),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 1,
                      child: ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState?.validate() ?? false) {
                            _formKey.currentState!.save();
                            modal.changeStep(1);
                          }
                        },
                        child: const Text('Next'),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      );
    });
  }
}

3. 修改第二步表单(form-question2.dart)

与第一步逻辑一致,绑定对应状态字段:

class FormQuestion2 extends StatefulWidget {
  const FormQuestion2({super.key});
  static const routeName = '/form-question2';

  @override
  State<FormQuestion2> createState() => _FormQuestion2State();
}

class _FormQuestion2State extends State<FormQuestion2> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Consumer<Create>(builder: (context, modal, child) {
      return Form(
        key: _formKey,
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              TextFormField(
                initialValue: modal.question2Title,
                decoration: const InputDecoration(
                  labelText: 'title',
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value!.isEmpty)
                    return 'Please enter the title of question';
                },
                onChanged: (value) {
                  modal.question2Title = value;
                  modal.notifyListeners();
                },
              ),
              const SizedBox(height: 16),
              TextFormField(
                initialValue: modal.question2Description,
                minLines: 3,
                maxLines: 5,
                decoration: const InputDecoration(
                  labelText: 'description',
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value!.isEmpty || value.length < 30) {
                    return 'Description must be longer';
                  }
                },
                onChanged: (value) {
                  modal.question2Description = value;
                  modal.notifyListeners();
                },
              ),
              Padding(
                padding: const EdgeInsets.all(10),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Expanded(
                      flex: 1,
                      child: ElevatedButton(
                        onPressed: () {
                          _formKey.currentState?.save();
                          modal.changeStep(0);
                        },
                        child: const Text('Back'),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 2,
                      child: ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState?.validate() ?? false) {
                            _formKey.currentState!.save();
                            // 此处添加提交逻辑
                            print('提交数据:${modal.question2Title}, ${modal.question2Description}');
                          }
                        }, 
                        child: const Text('Submit'),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 1,
                      child: ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState?.validate() ?? false) {
                            _formKey.currentState!.save();
                            modal.changeStep(2);
                          }
                        },
                        child: const Text('Next'),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      );
    });
  }
}

关键修改点说明

  • 状态隔离:为每个步骤的字段单独命名,避免数据覆盖
  • 双向绑定:通过initialValue恢复历史输入,onChanged实时同步到全局状态,确保切换页面时数据不丢失
  • 逻辑修正:调整步骤切换逻辑,Back按钮返回上一步,Next按钮跳转至正确的下一个步骤

内容的提问来源于stack exchange,提问作者best_of_man

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 02:57:52