forms - 如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter

标签 forms flutter dart statefulwidget

我在有状态小部件中有一个表单,在我的有状态小部件中,我使用提交方法验证我的表单。

在我的应用中,我在另一个 dart 文件的另一个页面中显示该表单。

我的表单在新页面和 appbar 操作中可见,我正在调用提交方法,但我不知道如何在新 dart 文件中调用该提交方法。

最佳答案

我认为你的问题不是验证逻辑,你可以在回调中做到这一点
我认为您的情况是单击提交按钮时您可能会使用 SnackBar。您使用 SnackBar 来显示错误,并且您不想在 appbar 中重复此逻辑。

诀窍是使用 GlobalKey 保持 YourFormState 并在 YourFormState 中使用 key.currentState 调用函数,因此提交按钮和 appbar Action 可以调用相同的函数

final key = new GlobalKey<MyCustomFormState>();
...
appBar: AppBar(          
          title: Text(widget.title),
          actions: <Widget>[
            // action button
            IconButton(
              icon: Icon(Icons.access_alarm),
              onPressed: () {
                key.currentState.validateform();
              },
            ),
          ]),
...
children: <Widget>[
        MyCustomForm(key: key),

... 

class MyCustomForm extends StatefulWidget {
  MyCustomForm({ Key key }) : super(key: key);

完整的工作代码

import 'package:flutter/material.dart';

void main() => runApp(MyApp());
final key = new GlobalKey<MyCustomFormState>();

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}
var myCustomForm =  MyCustomForm();

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
          actions: <Widget>[
      // action button
      IconButton(
      icon: Icon(Icons.access_alarm),
      onPressed: () {
        key.currentState.validateform();
      },
    ),
      ]),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            MyCustomForm(key: key),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class MyCustomForm extends StatefulWidget {
  MyCustomForm({ Key key }) : super(key: key);

  @override
  MyCustomFormState createState() {
    return MyCustomFormState();
  }

}

// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
  // Create a global key that uniquely identifies the Form widget
  // and allows validation of the form.
  //
  // Note: This is a GlobalKey<FormState>,
  // not a GlobalKey<MyCustomFormState>.
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    // Build a Form widget using the _formKey created above.
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          TextFormField(
            validator: (value) {
              if (value.isEmpty) {
                return 'Please enter some text';
              }
              return null;
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: RaisedButton(
              onPressed: () {
                // Validate returns true if the form is valid, or false
                // otherwise.
                validateform();
              },
              child: Text('Submit'),
            ),
          ),
        ],
      ),
    );
  }

  void validateform() {
    // Validate returns true if the form is valid, or false
    // otherwise.
    if (_formKey.currentState.validate()) {
      // If the form is valid, display a Snackbar.
      Scaffold.of(context)
          .showSnackBar(SnackBar(content: Text('Processing Data')));
    }
  }
}

demo 与 SnackBar 配合使用
enter image description here

关于forms - 如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57721371/

相关文章:

javascript - 上传从网络摄像头拍摄的图片

PHP 表单插入 Db 内的特定表

javascript - 跟踪基本 HTML 表单发布进度

forms - 使用 FieldArray 字段初始化 redux 表单

dart - 如何使用 flutter 删除 Firestore 文档中的字段

flutter - 滑动触发功能

Flutter 在 ListView 顶部显示小部件,可以在滚动时滑动

flutter - 如何制作带有渐变背景的 Flutter 应用栏

android - flutter - 在 null 上调用了方法 '[]'(解析 json)

Dart Error Handling 具体错误