1

我已经使用 TextFormFields 和 DropdownButtons 构建了一个 Flutter 表单来编辑用户配置文件。初始值是使用 FutureBuilder 从 Firebase 调用的。下拉列表中的列表也是从 Firebase 流式传输的。

问题一:在DropdownButtons中,选择后initialvalues没有变化;Firebase 的值保留在表单中。但是,当您单击“保存”按钮时,它会正确更新 Firebase 的选择。如何覆盖初始值?我已经尝试了很多东西,但我假设这是一个州问题。

问题 2:如何向 DropdownButton 添加验证器以确保它不是空的?我不能让它工作。

太感谢了!

截屏

class EditProfilePage extends StatefulWidget {
  const EditProfilePage({Key key, @required this.database, this.profile})
      : super(key: key);
  final FirestoreDatabase database;
  final Profile profile;

  static Future<void> show(
    BuildContext context, {
    FirestoreDatabase database,
    Profile profile,
  }) async {
    await Navigator.of(context, rootNavigator: true).push(
      MaterialPageRoute(
        builder: (context) =>
            EditProfilePage(database: database, profile: profile),
        fullscreenDialog: true,
      ),
    );
  }

  @override
  _EditProfilePageState createState() => _EditProfilePageState();
}

class _EditProfilePageState extends State<EditProfilePage> {
  final _formKey = GlobalKey<FormState>();

  String userId;
  String name;
  String gender;
  String relationshipStatus;

  var _selectedGender;
  var _selectedRelationshipStatus;

  bool _validateAndSaveForm() {
    final form = _formKey.currentState;
    if (form.validate()) {
      form.save();
      return true;
    }
    return false;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 2.0,
        title: Text('Edit Profile'),
      ),
      body: _buildContents(),
      backgroundColor: Colors.grey[200],
    );
  }

  Widget _buildContents() {
    return SingleChildScrollView(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Card(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: _buildForm(),
          ),
        ),
      ),
    );
  }

  Widget _buildForm() {
    return Form(
      key: _formKey,
      child: _buildFormChildren(),
    );
  }

  Widget _buildFormChildren() {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return FutureBuilder<DocumentSnapshot>(
      future: FirebaseFirestore.instance
          .collection('users')
          .doc(auth.currentUser.uid)
          .get(),
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
        List<Widget> children;
        if (snapshot.hasData) {
          _selectedGender = snapshot.data['gender'];
          _selectedRelationshipStatus = snapshot.data['relationshipStatus'];
          children = <Widget>[
            TextFormField(
              decoration: InputDecoration(labelText: 'Name'),
              initialValue: snapshot.data['name'],
              validator: (value) =>
                  value.isNotEmpty ? null : 'Name can\'t be empty',
              onSaved: (value) => name = value,
            ),
            FormField(
                initialValue: _selectedGender,
                builder: (FormFieldState state) {
                  return InputDecorator(
                    decoration: InputDecoration(
                      labelText: 'Gender',
                    ),
                    child: StreamBuilder<QuerySnapshot>(
                        stream: FirebaseFirestore.instance
                            .collection('references')
                            .doc('profile_references')
                            .collection('gender')
                            .snapshots(),
                        builder: (context, snapshot) {
                          if (!snapshot.hasData)
                            return const Center(
                              child: const CircularProgressIndicator(),
                            );
                          var length = snapshot.data.docs.length;
                          DocumentSnapshot ds = snapshot.data.docs[length - 1];
                          return DropdownButton(
                            isDense: true,
                            value: _selectedGender,
                            hint: Text('Change to'),
                            items: snapshot.data.docs
                                .map((DocumentSnapshot document) {
                              return DropdownMenuItem(
                                value: document.data()['gender'],
                                child: Text(document.data()['gender']),
                              );
                            }).toList(),
                            onChanged: (value) {
                              setState(() {
                                gender = value;
                                _selectedGender = value;
                              });
                            },
                          );
                        }),
                  );
                }),
            FormField(
                initialValue: _selectedRelationshipStatus,
                builder: (FormFieldState state) {
                  return InputDecorator(
                    decoration: InputDecoration(
                      labelText: 'Relationship Status',
                    ),
                    child: StreamBuilder<QuerySnapshot>(
                        stream: FirebaseFirestore.instance
                            .collection('references')
                            .doc('profile_references')
                            .collection('relationshipStatus')
                            .snapshots(),
                        builder: (context, snapshot) {
                          if (!snapshot.hasData)
                            return const Center(
                              child: const CircularProgressIndicator(),
                            );
                          var length = snapshot.data.docs.length;
                          DocumentSnapshot ds = snapshot.data.docs[length - 1];
                          return DropdownButton(
                            isDense: true,
                            value: _selectedRelationshipStatus,
                            hint: Text('Change to'),
                            items: snapshot.data.docs
                                .map((DocumentSnapshot document) {
                              return DropdownMenuItem(
                                value: document.data()['relationshipStatus'],
                                child:
                                    Text(document.data()['relationshipStatus']),
                              );
                            }).toList(),
                            onChanged: (value) {
                              setState(() {
                                relationshipStatus = value;
                                _selectedRelationshipStatus = value;
                              });
                            },
                          );
                        }),
                  );
                }),
          ];
        } else if (snapshot.hasError) {
          children = <Widget>[
            Icon(
              Icons.error_outline,
              color: Colors.red,
              size: 60,
            ),
            Padding(
              padding: const EdgeInsets.only(top: 16),
              child: Text('Error: ${snapshot.error}'),
            )
          ];
        } else {
          children = <Widget>[
            SizedBox(
              child: CircularProgressIndicator(),
              width: 60,
              height: 60,
            ),
            const Padding(
              padding: EdgeInsets.only(top: 16),
              child: Text('Awaiting result...'),
            )
          ];
        }
        return Center(
          child: SingleChildScrollView(
            child: Column(
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: children,
                ),
                SizedBox(height: 20),
                RaisedButton(
                  color: Colors.green[100],
                  child: Text(
                    'Save',
                    style: TextStyle(fontSize: 18, color: Colors.black),
                  ),
                  onPressed: () async {
                    if (_validateAndSaveForm()) {
                      try {
                        {
                          final profile = Profile(
                              name: name,
                              gender: gender,
                              relationshipStatus: relationshipStatus);
                          await widget.database.editProfile(profile);
                          Navigator.of(context).pop();
                        }
                      } on FirebaseException catch (e) {
                        showExceptionAlertDialog(
                          context,
                          title: 'Operation failed',
                          exception: e,
                        );
                      }
                    }
                  },
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

4

0 回答 0