因此,基本上我有一个ProfilePage
,它是一个StatelessWidget
,在其构建方法中,我显示了一个名为MyForm
的表单,它是一个StatefulWidget
和一个名为{ {1}},这是另一个FancyFab
。
以下是它们在父窗口小部件上如何显示的示例:
StatefulWidget
我的问题在于,我在@override
Widget build(BuildContext globalContext) {
return Scaffold(
appBar: AppBar(title: Text('Profile')),
floatingActionButton: FancyFab(),
body: Center(
child: FutureBuilder(
future: initData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return MyForm(data: snapshot.data);
} else if (snapshot.hasError) {
print(snapshot.error);
return new Container(width: 0.0, height: 0.0);
} else {
return Center(child: CircularProgressIndicator());
}
},
)
)
);
}
中有一个saveData()
函数,该函数从每个MyFormState
控制器中获取值并将其保存在数据库中。我需要从TextFormField
小部件中调用此函数,但是找不到合适的方法。甚至甚至可以从我的FancyFab
小部件中访问那些TextFormField
控制器。任何帮助或指导将不胜感激。
编辑
这是我实现FancyFab
小部件的方式:
FancyFab
答案 0 :(得分:0)
据我所知,应用程序的数据流有一个小问题,例如,严格地基于基于功能的观察,数据和触发器(FancyFab)应该位于同一小部件中或位于可直接访问的小部件。但是,如果您想继续,here是一种非常原始的方法(非常简单)。
答案 1 :(得分:0)
我设法通过在Scaffold
小部件内嵌套MyForm
来解决此问题。然后树变了,我的FancyFab
小部件现在是MyForm
小部件的子级。接下来,我将父级的saveData()
函数和所有控制器传递给子控件,这样我就可以调用提供适当数据的父级函数。解决方法如下:
class MyFormState extends State<MyForm> {
User user;
TextEditingController birthController = TextEditingController();
TextEditingController firstController = TextEditingController();
TextEditingController lastController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController phoneController = TextEditingController();
TextEditingController associationController = TextEditingController();
TextEditingController countryController = TextEditingController();
@override
void initState() {
super.initState();
user = widget.data[1];
firstController.text = user.firstName;
lastController.text = user.lastName;
countryController.text = user.country;
birthController.text = user.dateBirth;
emailController.text = user.email;
phoneController.text = user.phone;
associationController.text = user.association;
}
_updatePhoto(String text) {
setState(() {
user.photo = text;
});
}
_saveData(data, BuildContext ctx) async {
FirebaseUser fireUser= await FirebaseAuth.instance.currentUser();
var uid = fireUser.uid;
await Firestore.instance.collection('users').document(uid).updateData(data).then((val) {
AlertDialog alert = AlertDialog(
title: Text('Confirmation'),
titlePadding: EdgeInsets.all(20.0),
// contentPadding: EdgeInsets.all(20.0),
elevation:10,
content: Text('Your profile has been saved.')
);
showDialog(context: ctx,
builder: (BuildContext context){
return alert;
});
})
.catchError((err) {
final snackBar = SnackBar(
content: Text('There have been an error updating your profile' + err.toString()),
elevation: 10,
);
Scaffold.of(ctx).showSnackBar(snackBar);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FancyFab(
parentAction: _updatePhoto,
saveData: _saveData,
firstController: firstController,
lastController: lastController,
emailController: emailController,
countryController: countryController,
associationController: associationController,
phoneController: phoneController,
birthController: birthController,
photo: user.photo),
body:Form(
//more UI
)
);
}
}
class FancyFab extends StatefulWidget {
final void Function(String value) parentAction;
final void Function(dynamic data, BuildContext ctx) saveData;
final String tooltip;
final IconData icon;
String photo;
TextEditingController birthController;
TextEditingController firstController;
TextEditingController lastController;
TextEditingController emailController;
TextEditingController phoneController;
TextEditingController associationController;
TextEditingController countryController;
FancyFab({
this.parentAction,
this.tooltip,
this.icon,
this.saveData,
this.firstController,
this.lastController,
this.emailController,
this.phoneController,
this.associationController,
this.countryController,
this.birthController,
this.photo});
@override
_FancyFabState createState() => _FancyFabState();
}
然后我可以在子窗口小部件状态上使用widget.parentFunction(data)
调用父函数。
特别感谢 @diegoveloper 提供了一篇很棒的文章,解释了小部件交互的类型。