从另一个StatefulWidget的Stateful Widget调用函数

时间:2019-07-18 18:42:17

标签: flutter dart

因此,基本上我有一个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

2 个答案:

答案 0 :(得分:0)

据我所知,应用程序的数据流有一个小问题,例如,严格地基于基于功能的观察,数据和触发器(FancyFab)应该位于同一小部件​​中或位于可直接访问的小部件。但是,如果您想继续,here是一种非常原始的方法(非常简单)。

答案 1 :(得分:0)

我设法通过在Scaffold小部件内嵌套MyForm来解决此问题。然后树变了,我的FancyFab小部件现在是MyForm小部件的子级。接下来,我将父级的saveData()函数和所有控制器传递给子控件,这样我就可以调用提供适当数据的父级函数。解决方法如下:

解决方案

父小部件(MyForm)

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
            )
           );
   }
}

Child小部件(FancyFab)

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 提供了一篇很棒的文章,解释了小部件交互的类型。