Tayo.dev
Tayo.dev

Reputation: 1656

Flutter: Get values of Multiple TextFormField in Dart

I'm using floatingActionButton to increase TextForm Fields. i.e the fields increase by 1 once the button is tapped. The fields are actually increased on tap of the button but so confused on how to get values for each fields generated.

My problems:

  1. When the user selects a value in the dropdown, all the values in the other generated dropdown fields changes to the new one. How do I solve this?

  2. I'd like to add all the number value of the each of the generated Grade field together and also add the value of each of the generated Course Unit field together. i.e Add(sum) the value of all Grade fields the user generated.

See my full code below:

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),
      ),

    );
  }
}

Upvotes: 1

Views: 2914

Answers (1)

Omatt
Omatt

Reputation: 10443

When the user selects a value in the dropdown, all the values in the other generated dropdown fields changes to the new one. How do I solve this?

The reason why DropdownButton children in ListView updates synchronously is because it fetches all its value from the _unit variable. I suggest using a List<Object> to manage the data of ListView items.

i.e.

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

...

List<Course> _listCourse = [];

I'd like to add all the number value of the each of the generated Grade field together and also add the value of each of the generated Course Unit field together. i.e Add(sum) the value of all Grade fields the user generated.

With ListView data being managed in List<Course>, data inputted in the fields can be set in onChanged()

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

and the values can be summed up with the help of a foreach loop.

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

Here's a complete working sample based from the snippet you've shared.

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

Upvotes: 1

Related Questions