Flutter提供程序,在提供程序中使用GlobalKey <FormState>的正确方法

时间:2019-07-09 08:27:32

标签: flutter dart

我是Provider package.的新手,只是制作用于学习目的的演示应用。

这是我的简单Form Widget的代码。

1)注册页面 (我的应用开始的位置)

class RegistrationPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text("Title"),
      ),
      body: MultiProvider(providers: [
        ChangeNotifierProvider<UserProfileProvider>.value(value: UserProfileProvider()),
        ChangeNotifierProvider<RegiFormProvider>.value(value: RegiFormProvider()),
      ], child: AllRegistrationWidgets()),
    );
  }
}

class AllRegistrationWidgets extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).requestFocus(FocusNode());
      },
      child: Container(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Expanded(
              child: SingleChildScrollView(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    SetProfilePicWidget(),
                    RegistrationForm(),
                  ],
                ),
              ),
            ),
            BottomSaveButtonWidget()
          ],
        ),
      ),
    );
  }
}

class BottomSaveButtonWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _userPicProvider =
        Provider.of<UserProfileProvider>(context, listen: false);

    final _formProvider =
    Provider.of<RegiFormProvider>(context, listen: false);

    return SafeArea(
      bottom: true,
      child: Container(
          margin: EdgeInsets.all(15),
          child: FloatingActionButton.extended(
            heroTag: 'saveform',
            icon: null,
            label: Text('SUBMIT',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                )),
            onPressed: () {
               print(_userPicProvider.strImageFileName);
              _formProvider.globalFormKey.currentState.validate();

              print(_formProvider.firstName);
              print(_formProvider.lastName);
            },
          )),
    );
  }
}

2)注册表格

class RegistrationForm extends StatefulWidget {
  @override
  _RegistrationFormState createState() => _RegistrationFormState();
}

class _RegistrationFormState extends State<RegistrationForm> {
  TextEditingController _editingControllerFname;
  TextEditingController _editingControllerLname;

  @override
  void initState() {
    _editingControllerFname = TextEditingController();
    _editingControllerLname = TextEditingController();    

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final formProvider = Provider.of<RegiFormProvider>(context);
    return _setupOtherWidget(formProvider);
  }

  _setupOtherWidget(RegiFormProvider _formProvider) {
    return Container(
      padding: EdgeInsets.all(12),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          SizedBox(height: 20),
          Text(
            'Fields with (*) are required.',
            style: TextStyle(fontStyle: FontStyle.italic),
            textAlign: TextAlign.left,
          ),
          SizedBox(height: 20),
          _formSetup(_formProvider)
        ],
      ),
    );
  }

  _formSetup(RegiFormProvider _formProvider) {
    return Form(
      key: _formProvider.globalFormKey,
      child: Container(
        child: Column(
          children: <Widget>[
            TextFormField(
                controller: _editingControllerFname,
                textCapitalization: TextCapitalization.sentences,
                decoration: InputDecoration(
                  labelText: "First Name *",
                  hintText: "First Name *",
                ),
                onSaved: (value) {},
                validator: (String value) =>
                    _formProvider.validateFirstName(value)),
            SizedBox(height: 15),
            TextFormField(
              controller: _editingControllerLname,
              textCapitalization: TextCapitalization.sentences,
              validator: (String value) =>
                  _formProvider.validateLastName(value),
              onSaved: (value) {},
              decoration: InputDecoration(
                labelText: "Last Name *",
                hintText: "Last Name *",
              ),
            )                           
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _editingControllerFname.dispose();
    _editingControllerLname.dispose();    
    super.dispose();
  }
}

3)RegiFormProvider

class RegiFormProvider with ChangeNotifier {

  final GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();

  String _strFirstName;
  String _strLasttName;

  String get firstName => _strFirstName;
  String get lastName => _strLasttName;

  String validateFirstName(String value) {
    if (value.trim().length == 0)
      return 'Please enter first name';
    else {
      _strFirstName = value;
      return null;
    }
  }

  String validateLastName(String value) {
    if (value.trim().length == 0)
      return 'Please enter last name';
    else {
      _strLasttName = value;
      return null;
    }
  }

}

在这里您可以看到RegiFormProvider是我的第一页,其他是窗口小部件树中的子窗口小部件。我在final GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();提供者中使用RegiFormProvider,因为我想在第一个RegistrationPage中访问它,以检查我的 firstName和lastName 是否有效。

1 个答案:

答案 0 :(得分:0)

我正在使用一个构建器小部件来获取如下所示的表单级上下文,然后我们可以轻松地通过使用该上下文来获取表单实例。通过这种方式,我们不再需要全局密钥。

Form(
        child: Builder(
          builder: (ctx) {
            return ListView(
              padding: EdgeInsets.all(12),
              children: <Widget>[
                TextFormField(
                  decoration: InputDecoration(labelText: "Title"),
                  textInputAction: TextInputAction.next,
                  onFieldSubmitted: (_) => FocusScope.of(context).nextFocus(),
                  initialValue: formProduct.title,
                  validator: validateTitle,
                  onSaved: (value) {
                    formProduct.title = value;
                  },
                ),
                TextFormField(
                  decoration: InputDecoration(labelText: "Price"),
                  textInputAction: TextInputAction.next,
                  onFieldSubmitted: (_) => FocusScope.of(context).nextFocus(),
                  initialValue: formProduct.price == null
                      ? ""
                      : formProduct.price.toString(),
                  keyboardType: TextInputType.number,
                  validator: validatePrice,
                  onSaved: (value) {
                    formProduct.price = double.parse(value);
                  },
                ),
                TextFormField(
                  decoration: InputDecoration(labelText: "Description"),
                  textInputAction: TextInputAction.next,
                  initialValue: formProduct.description,
                  maxLines: 3,
                  validator: validateDescription,
                  onFieldSubmitted: (_) => FocusScope.of(context).nextFocus(),
                  onSaved: (value) {
                    formProduct.description = value;
                  },
                ),
                TextFormField(
                  decoration: InputDecoration(labelText: "Image Url"),
                  textInputAction: TextInputAction.done,
                  onFieldSubmitted: (_) => FocusScope.of(context).unfocus(),
                  initialValue: formProduct.imageUrl,
                  validator: validateImageUrl,
                  onSaved: (value) {
                    formProduct.imageUrl = value;
                  },
                ),
                Padding(
                  padding: EdgeInsets.all(10),
                  child: FlatButton(
                    color: Colors.amberAccent,
                    onPressed: () {
                      if (Form.of(ctx).validate()) {
                        Form.of(ctx).save();
                        formProduct.id =
                            Random.secure().nextDouble().toString();
                        ProductsProvider provider =
                            Provider.of<ProductsProvider>(context,
                                listen: false);
                        editing
                            ? provider.setProduct(formProduct)
                            : provider.addProduct(formProduct);
                        Router.back(context);
                      }
                    },
                    child: Text("Save"),
                  ),
                )
              ],
            );
          },
        ),
      )

您会看到Form.of(ctx)给了我们当前的关卡表格。