获取多个文本字段值的最佳方法

时间:2019-09-26 12:50:06

标签: flutter dart

我正在制作一个包含多个TextField(例如超过12个)的数据收集应用程序。我正在使用Form键来验证所有这些应用程序。我需要所有文本字段的值,以便将其保存到Firestore。我该怎么做呢?这是我的代码:

import 'package:flutter/material.dart';

class MainForm extends StatefulWidget {
  @override
  _MainFormState createState() => _MainFormState();
}

class _MainFormState extends State<MainForm> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Center(
      child: SingleChildScrollView(
        child: Form(
          key: _formKey,
          child: Column(
            children: <Widget>[
              Text('Enter information about PG Owner'),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextField(
                  autofocus: true,
                  textCapitalization: TextCapitalization.words,
                  textAlignVertical: TextAlignVertical.center,
                  onTap: () {},
                  decoration: InputDecoration(
                      prefixIcon: Icon(Icons.face),
                      labelText: 'Enter Name of Owner',
                      border: OutlineInputBorder()),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextFormField(
                  validator: (value) {
                    if (value.length < 15) {
                      return 'Address seems very short!';
                    }
                    return null;
                  },
                  keyboardType: TextInputType.text,
                  decoration: InputDecoration(
                      prefixIcon: Icon(Icons.room),
                      labelText: 'Enter full address of Owner',
                      border: OutlineInputBorder()),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextFormField(
                  keyboardType: TextInputType.number,
                  validator: (value) {
                    if (value.length < 9) {
                      return 'Phone number must be 9 digits or longer';
                    }
                    return null;
                  },
                  decoration: InputDecoration(
                      prefixIcon: Icon(Icons.phone),
                      labelText: 'Phone number of Owner',
                      border: OutlineInputBorder()),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextFormField(
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Please enter a valid email address';
                    }
                    if (!value.contains('@')) {
                      return 'Email is invalid, must contain @';
                    }
                    if (!value.contains('.')) {
                      return 'Email is invalid, must contain .';
                    }
                    return null;
                  },
                  keyboardType: TextInputType.emailAddress,
                  decoration: InputDecoration(
                      prefixIcon: Icon(Icons.mail_outline),
                      labelText: 'Enter Email',
                      border: OutlineInputBorder()),
                ),
              ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

更新:我知道从TextField获取值的正确方法(我已经阅读了文档)是通过创建一个控制器。但是,就我而言,有14个TextField,这需要我创建14个控制器。有更好的方法吗?

3 个答案:

答案 0 :(得分:10)

您可以在以下代码中使用类似的内容:

_formKey.currentState.save(); 在每个textFormField项上调用 onSaved(),这会将值分配给所有字段您可以根据需要使用它们。在 _formKey.currentState.validate()被评估为true之后,尝试使用 _formKey.currentState.save();

表单代码如下:

String contactNumber;
String pin;
return Form(
  key: _formKey,
  child: Column(
    children: <Widget>[
      TextFormField(
        onSaved: (String value){contactNumber=value;},
        keyboardType: TextInputType.phone,
        inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
        maxLength: 10,
        decoration: InputDecoration(
            labelText: "Enter Your Mobile Number",
            hintText: "Number",
            icon: Icon(Icons.phone_iphone)),
        validator: (value) {
          if (value.isEmpty || value.length < 10) {
            return 'Please Enter 10 digit number';
          }
          return null;
        },
      ),
      TextFormField(
        onSaved: (String value){pin=value;},
        keyboardType: TextInputType.phone,
        inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
        maxLength: 10,
        decoration: InputDecoration(
            labelText: "Enter Your PIN",
            hintText: "Number",
            icon: Icon(Icons.lock)),
        validator: (value) {
          if (value.isEmpty || value.length < 6) {
            return 'Please Enter 6 digit PIN';
          }
          return null;
        },
      ),
      Padding(
        padding: const EdgeInsets.symmetric(vertical: 16.0),
        child: RaisedButton(
            color: Colors.black,
            textColor: Colors.white,
            onPressed: () {
              if (_formKey.currentState.validate()) {
                ***_formKey.currentState.save();***
                bloc.loginUser(contactNumber, pin);
              }
            },
            child: Text('Login' /*style: TextStyle(fontSize: 30),*/)),
      )
    ],
  ),
);

答案 1 :(得分:1)

您可以使用flutter_form_bloc,不需要创建任何TextEditingController,并且除了提供其他优势之外,还可以将业务逻辑与用户界面分开。

dependencies:
  flutter_bloc: ^0.21.0
  form_bloc: ^0.4.1
  flutter_form_bloc: ^0.3.0
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:form_bloc/form_bloc.dart';

void main() => runApp(MaterialApp(home: MainForm()));

class MainFormBloc extends FormBloc<String, String> {
  final nameField = TextFieldBloc();
  final addressField = TextFieldBloc(validators: [
    (value) => value.length < 15 ? 'Address seems very short!' : null,
  ]);
  final phoneNumberField = TextFieldBloc(validators: [
    (value) =>
        value.length < 9 ? 'Phone number must be 9 digits or longer' : null,
  ]);
  final emailField = TextFieldBloc(validators: [Validators.email]);

  @override
  List<FieldBloc> get fieldBlocs => [
        nameField,
        addressField,
        phoneNumberField,
        emailField,
      ];

  @override
  Stream<FormBlocState<String, String>> onSubmitting() async* {
    // This method is called when you call [mainFormBloc.submit]
    // and each field bloc have a valid value.
    // And you can save them in firestore.
    print(nameField.value);
    print(addressField.value);
    print(phoneNumberField.value);
    print(emailField.value);

    yield currentState.toSuccess('Data saved successfully.');

    // yield `currentState.toLoaded()` because
    // you can't submit if the state is `FormBlocSuccess`.
    // In most cases you don't need to do this,
    // because you only want to submit only once.
    yield currentState.toLoaded();
  }
}

class MainForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<MainFormBloc>(
      builder: (context) => MainFormBloc(),
      child: Builder(
        builder: (context) {
          final formBloc = BlocProvider.of<MainFormBloc>(context);

          return Scaffold(
            appBar: AppBar(title: Text('Main Form')),
            body: FormBlocListener<MainFormBloc, String, String>(
              onSuccess: (context, state) {
                Scaffold.of(context).showSnackBar(
                  SnackBar(
                    content: Text(state.successResponse),
                    backgroundColor: Colors.green,
                  ),
                );
              },
              onSubmissionFailed: (context, state) {
                Scaffold.of(context).showSnackBar(
                  SnackBar(
                    content: Text('Some fields have invalid data.'),
                    backgroundColor: Colors.red,
                  ),
                );
              },
              child: ListView(
                children: <Widget>[
                  TextFieldBlocBuilder(
                    textFieldBloc: formBloc.nameField,
                    padding: const EdgeInsets.all(8.0),
                    autofocus: true,
                    textCapitalization: TextCapitalization.words,
                    textAlignVertical: TextAlignVertical.center,
                    decoration: InputDecoration(
                        prefixIcon: Icon(Icons.face),
                        labelText: 'Enter Name of Owner',
                        border: OutlineInputBorder()),
                  ),
                  TextFieldBlocBuilder(
                    textFieldBloc: formBloc.addressField,
                    padding: const EdgeInsets.all(8.0),
                    keyboardType: TextInputType.text,
                    decoration: InputDecoration(
                        prefixIcon: Icon(Icons.room),
                        labelText: 'Enter full address of Owner',
                        border: OutlineInputBorder()),
                  ),
                  TextFieldBlocBuilder(
                    textFieldBloc: formBloc.phoneNumberField,
                    padding: const EdgeInsets.all(8.0),
                    keyboardType: TextInputType.number,
                    decoration: InputDecoration(
                        prefixIcon: Icon(Icons.phone),
                        labelText: 'Phone number of Owner',
                        border: OutlineInputBorder()),
                  ),
                  TextFieldBlocBuilder(
                    textFieldBloc: formBloc.emailField,
                    padding: const EdgeInsets.all(8.0),
                    keyboardType: TextInputType.emailAddress,
                    decoration: InputDecoration(
                        prefixIcon: Icon(Icons.mail_outline),
                        labelText: 'Enter Email',
                        border: OutlineInputBorder()),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: RaisedButton(
                      onPressed: formBloc.submit,
                      child: Center(child: Text('SUBMIT')),
                    ),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

答案 2 :(得分:0)

使用TextFormField中的控制器,您可以获取TextFormField的值。

TextEditingController emailEditingController = TextEditingController();
TextFormField(
  controller: emailEditingController,
  validator: (value) {
    if (value.isEmpty) {
      return 'Please enter a valid email address';
    }
    if (!value.contains('@')) {
      return 'Email is invalid, must contain @';
    }
    if (!value.contains('.')) {
      return 'Email is invalid, must contain .';
    }
    return null;
  },
  keyboardType: TextInputType.emailAddress,
  decoration: InputDecoration(
      prefixIcon: Icon(Icons.mail_outline),
      labelText: 'Enter Email',
      border: OutlineInputBorder()),
);

像这样获得价值

String email=emailEditingController.text;

更新后的答案

使用onSubmitted获取价值

onSubmitted: (String value){email=value;},