Flutter:在Dart中获取Multiple TextFormField的值

时间:2018-07-14 21:34:10

标签: dart flutter

我正在使用floatingActionButton来增加TextForm字段。即,一旦点击按钮,字段将增加1。轻按按钮实际上增加了字段,但是对于如何获取每个生成的字段的值却感到困惑。

我的问题:

  1. 当用户在下拉列表中选择一个值时,其他生成的下拉字段中的所有值都将更改为新值。请问我该如何解决?

  2. 我想将每个生成的Grade字段的所有数字值加在一起,并且还要将每个生成的Course Unit字段的所有值加在一起。即,将用户生成的所有Grade字段的值相加(求和)。请帮忙。

请参阅下面的完整代码:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'My Grade Point',
      theme: new ThemeData(primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isLoading = false;
  final formKey = new GlobalKey<FormState>();
  final scaffoldKey = new GlobalKey<ScaffoldState>();
  String _course;
  String _grade;
  String _unit;
  String _mygp;
  String _units;
  String _totalgrade;
  int counter = 1;

  void _submit() {
    final form = formKey.currentState;

    if (form.validate()) {
      setState(() => _totalgrade = _grade);
      form.save();
    }
  }
  Widget buildfields(int index) {
    return new Column(
      children: <Widget>[
        new TextFormField(
          onSaved: (String value) {
            setState((){
              _course = value;
            });
          },
          validator: (val) {
            return val.isEmpty
                ? "Enter Course Title $index"
                : null;
          },
          decoration: new InputDecoration(labelText: "Course Title"),
        ),
        new Row(
          children: <Widget>[
            new Expanded(
              child: new TextFormField(
                onSaved: (value) {
                  setState((){
                    _grade = value;
                  });
                  },
                keyboardType: TextInputType.number,
                decoration: new InputDecoration(labelText: "Grade"),
              ),
            ),
            new Expanded(
              child: new DropdownButton<String>(
                onChanged: (String value) { setState((){
                  _unit = value;
                });
                },
                hint: new Text('Course Unit'),
                value: _unit,
                items: <String>["1", "2", "3", "4", "5"].map((String value) {
                  return new DropdownMenuItem<String>(
                    value: value,
                    child: new Text(value),
                  );
                }).toList(),
              ),
            ),
          ],
        ),
      ],
    );
  }
  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;
    var loginBtn = new RaisedButton(
      onPressed: _submit,
      child: new Text("CALCULATE"),
      color: Colors.primaries[0],
    );
    var showForm = new Container(
      padding: new EdgeInsets.all(20.0),
      child: new Column(
        children: <Widget>[
          new Expanded(child: new Form(
            key: formKey,
            child: new ListView.builder(
              itemBuilder: (BuildContext context, int index) {
                return buildfields(index); },
              itemCount: counter,
              scrollDirection: Axis.vertical,
            ),
          ),
          ),
          _isLoading ? new CircularProgressIndicator() : loginBtn
        ],
      ),
    );
    return new Scaffold(
      appBar: new 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: new Text(_totalgrade.toString()),
      ),
      body: showForm,
      floatingActionButton: new FloatingActionButton(
          onPressed: () {
            setState(() {
              counter++;
            });
          },
          child: new Icon(Icons.add),
      ),

    );
  }
}

1 个答案:

答案 0 :(得分:1)

<块引用>

当用户在下拉列表中选择一个值时,其他生成的下拉字段中的所有值都会更改为新的值。我该如何解决这个问题?

ListView 中的 DropdownButton 子节点同步更新的原因是它从 _unit 变量中获取其所有值。我建议使用 List<Object> 来管理 ListView 项目的数据。

class Course {
  var title;
  var grade;
  var unit;
}

...

List<Course> _listCourse = [];
<块引用>

我想将每个生成的成绩字段的所有数值加在一起,并将每个生成的课程单元字段的值加在一起。即添加(总和)用户生成的所有成绩字段的值。

ListView数据在List<Course>中管理,字段输入的数据可以在onChanged()中设置

// Course Grade
TextFormField(
   onChanged: (String value) {
     setState(() {
       _listCourse[index].grade = value;
     });
   },
)

并且可以在 foreach 循环的帮助下总结这些值。

int sumGrade = 0;
_listCourse.forEach((course) {
  // Add up all Course Grade
  sumGrade += num.tryParse(course.grade);
});

这是基于您共享的代码段的完整工作示例。

Demo

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'My Grade Point',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class Course {
  var title;
  var grade;
  var unit;
}

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

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isLoading = false;
  final formKey = new GlobalKey<FormState>();
  final scaffoldKey = new GlobalKey<ScaffoldState>();
  String _course;
  int _grade;
  String _unit;
  String _mygp;
  String _units;
  int _totalGrade;
  int counter = 1;

  List<Course> _listCourse = [];

  @override
  void initState() {
    // Initialize empty List
    _listCourse.add(Course());
    super.initState();
  }

  void _submit() {
    debugPrint('List Course Length: ${_listCourse.length}');
    int sumGrade = 0;
    _listCourse.forEach((course) {
      debugPrint('Course Title: ${course.title}');
      debugPrint('Course Grade: ${course.grade}');
      // Add up all Course Grade
      sumGrade += num.tryParse(course.grade);
      debugPrint('Course Unit: ${course.unit}');
    });
    final form = formKey.currentState;

    if (form.validate()) {
      setState(() => _totalGrade = sumGrade);
      form.save();
    }
  }

  Widget buildField(int index) {
    return new Column(
      children: <Widget>[
        new TextFormField(
          onChanged: (String value) {
            setState(() {
              // _course = value;
              _listCourse[index].title = value;
            });
          },
          validator: (val) {
            return val.isEmpty ? "Enter Course Title $index" : null;
          },
          decoration: new InputDecoration(labelText: "Course Title"),
        ),
        new Row(
          children: <Widget>[
            new Expanded(
              child: new TextFormField(
                onChanged: (value) {
                  setState(() {
                    // _grade = value;
                    _listCourse[index].grade = value;
                  });
                },
                keyboardType: TextInputType.number,
                decoration: new InputDecoration(labelText: "Grade"),
              ),
            ),
            new Expanded(
              child: new DropdownButton<String>(
                onChanged: (String value) {
                  setState(() {
                    // _unit = value;
                    _listCourse[index].unit = value;
                  });
                },
                hint: new Text('Course Unit'),
                value: _listCourse[index].unit,
                items: <String>["1", "2", "3", "4", "5"].map((String value) {
                  return new DropdownMenuItem<String>(
                    value: value,
                    child: new Text(value),
                  );
                }).toList(),
              ),
            ),
          ],
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;
    var loginBtn = new RaisedButton(
      onPressed: _submit,
      child: new Text("CALCULATE"),
      color: Colors.primaries[0],
    );
    var showForm = new Container(
      padding: new EdgeInsets.all(20.0),
      child: new Column(
        children: <Widget>[
          new Expanded(
            child: new Form(
              key: formKey,
              child: ListView.builder(
                itemBuilder: (BuildContext context, int index) {
                  return buildField(index);
                },
                itemCount: counter,
                scrollDirection: Axis.vertical,
              ),
            ),
          ),
          _isLoading ? new CircularProgressIndicator() : loginBtn
        ],
      ),
    );
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(_totalGrade.toString()),
      ),
      body: showForm,
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          setState(() {
            // Add an empty Course object on the List
            _listCourse.add(Course());
            counter++;
          });
        },
        child: new Icon(Icons.add),
      ),
    );
  }
}