Romanoffa
Romanoffa

Reputation: 71

Flutter get snapshot.data[1] in future builder

I have the following code

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';

class MyData {
  String title;
  String days;
  String words;
  String rep;
  String gender;
  var username;

  MyData({this.gender, this.title, this.days, this.words, this.rep, this.username,
  });

}

class StepperBody extends StatefulWidget {
  @override
  _StepperBodyState createState() => _StepperBodyState();
}

class _StepperBodyState extends State<StepperBody> {
  int currStep = 0;
  static var _focusNode = FocusNode();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  Future<List<String>> _future;
  Future<List<String>> _car;

  List<GlobalKey<FormState>> formKeys = [
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>()
  ];

  String _key = "786465659081B207EB5BF1EF9AF7552A6";
  String _api = "https://10.0.2.2/api/";

  Future<void> senddata(List<String> username) async {
    final response = await http.post(
        _api + "insert_data.php?key=" + _key, body: {
      "username": username,
    });
    var resp = jsonDecode(response.body);
    print(resp.toString());
  }

  Future<List<String>> getData() async {
    var url = _api + "get_data.php?key=" + _key;
    http.Response response = await http.get(url);
    var resp = jsonDecode(response.body);
    print(resp.toString());
    return resp.map<String>((m) => m['username'] as String).toList();
  }

  Future<List<String>> getCar() async {
    var url = _api + "get_car.php?key=" + _key;
    http.Response response = await http.get(url);
    var resp = jsonDecode(response.body);
    print(resp.toString());
    return resp.map<String>((m) => m['plate'] as String).toList();
  }

  @override
  void initState() {
    super.initState();

    _future = getData();
    _car = getCar();

    _focusNode.addListener(() {
      setState(() {});
      print('Has focus: $_focusNode.hasFocus');
    });
  }


  @override
  Widget build(BuildContext context) {
    void showSnackBarMessage(String message,
        [MaterialColor color = Colors.red]) {
      Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
    }

    void _submitDetails(List<String> username) {
      final FormState formState = _formKey.currentState;
      final FormBuilderState fbKeyState = _fbKey.currentState;
/*
      _fbKey.currentState.save();
      if (_fbKey.currentState.validate()) {
        print(_fbKey.currentState.value);
      }

 */
      if (!fbKeyState.validate()) {
        showSnackBarMessage('Please enter correct data');
        senddata(username);

      } else {
        showSnackBarMessage('Saved');
        formState.save();
        senddata(username);
        print("Name: $username");



        _fbKey.currentState.save();
        if (_fbKey.currentState.validate()) {
          print(_fbKey.currentState.value);
        }
      }
    }

    return FutureBuilder<List<String>>(
        future: Future.wait([_future, _car]),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            final steps = [
              Step(
                title: const Text('Users'),
                //subtitle: const Text('Subtitle'),
                isActive: true,
                //state: StepState.editing,
                state: StepState.indexed,
                content: Form(
                  key: formKeys[0],
                  child: Column(
                    children: <Widget>[
                      FormBuilder(
                        key: _fbKey,
                        autovalidate: true,
                        child: FormBuilderCheckboxList(
                          decoration:
                          InputDecoration(labelText: "Languages you know"),
                          attribute: "languages",
                          initialValue: ["English"],
                          options: snapshot.data[0]
                              .map((languages) => FormBuilderFieldOption(
                              value: languages, child: Text("$languages")))
                              .toList(),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              Step(
                title: const Text('Users'),
                //subtitle: const Text('Subtitle'),
                isActive: true,
                //state: StepState.editing,
                state: StepState.indexed,
                content: Form(
                  key: formKeys[1],
                  child: Column(
                    children: <Widget>[
                      FormBuilder(
                        key: _fbKey,
                        autovalidate: true,
                        child: FormBuilderCheckboxList(
                          decoration:
                          InputDecoration(labelText: "Cars"),
                          attribute: "cars",
                          initialValue: ["BM-WD01"],
                          options: snapshot.data[1]
                              .map((car) => FormBuilderFieldOption(
                              value: car, child: Text("$car")))
                              .toList(),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ];

            return Container(
                child: Form(
                  key: _formKey,
                  child: ListView(children: <Widget>[
                    Stepper(
                      steps: steps,
                      physics: ClampingScrollPhysics(),
                      type: StepperType.vertical,
                      currentStep: this.currStep,
                      onStepContinue: () {
                        setState(() {
                          if (formKeys[currStep].currentState.validate()) {
                            if (currStep < steps.length - 1) {
                              currStep = currStep + 1;
                            } else {
                              currStep = 0;
                            }
                          }
                          // else {
                          // Scaffold
                          //     .of(context)
                          //     .showSnackBar( SnackBar(content:  Text('$currStep')));

                          // if (currStep == 1) {
                          //   print('First Step');
                          //   print('object' + FocusScope.of(context).toStringDeep());
                          // }

                          // }
                        });
                      },
                      controlsBuilder: (BuildContext context,
                          {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
                        return Row(
                          //   mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: <Widget>[
                            //
                            RaisedButton(
                              color: Colors.red,
                              child: Text("Forward",
                                  style: TextStyle(color: Colors.white)),
                              onPressed: onStepContinue,
                            ),

                            SizedBox(width: 15,),
                            RaisedButton(
                              color: Colors.red,
                              child: Text(
                                  "Back", style: TextStyle(color: Colors.white)),
                              onPressed: onStepCancel,
                            ),
                          ],
                        );
                      },
                      onStepCancel: () {
                        setState(() {
                          if (currStep > 0) {
                            currStep = currStep - 1;
                          } else {
                            currStep = 0;
                          }
                        });
                      },
                      onStepTapped: (step) {
                        setState(() {
                          currStep = step;
                        });
                      },
                    ),

                    RaisedButton(
                      child: Text(
                        'Save',
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () {
                        var submitDetails = _submitDetails;
                        submitDetails(snapshot.data);
                      },
                      color: Colors.lightGreen,
                    ),
                  ]),
                ));
          } else {
            return CircularProgressIndicator();
          }
        }
    );
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: "test",),
    );
  }
}

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

  final String title;

  @override
  MyAppScreenMode createState() => MyAppScreenMode();
}

class MyAppScreenMode extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    return new MaterialApp(
        theme: new ThemeData(
          primarySwatch: Colors.red,
        ),
        home: new Scaffold(

          appBar: new AppBar(
            title: new Text('Test stepper'),
          ),
          body: new StepperBody(),

        ));
  }
}

I want to display multiple lists from mySQL, the first function _future works fine, but when I replace future: _future to

future: Future.wait([_future, _car]),

I get an

The element type 'Future<List>' can't be assigned to the list type 'Future'

I have tried lots of other solutions but none of them works to use snapshot.data[0], snapshot.data1 and so on for more queries and data to display from different tables.

Can't get to work with more futurebuilders which would be even easier for each step own, but then I get enter image description here

      Step(
        title: const Text('Users'),
        //subtitle: const Text('Subtitle'),
        isActive: true,
        //state: StepState.editing,
        state: StepState.indexed,
        content: Form(
          key: formKeys[0],
          child:  FutureBuilder<List>(
            future: _future,
              // ignore: missing_return
            builder: (BuildContext context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                Column(
                  children: <Widget>[
                    FormBuilder(
                      key: _fbKey,
                      autovalidate: true,
                      child: FormBuilderCheckboxList(
                        decoration:
                        InputDecoration(
                            labelText: "Languages you know"),
                        attribute: "languages",
                        initialValue: ["English"],

                        options: snapshot.data
                            .map((gender) =>
                            FormBuilderFieldOption(
                                value: gender, child: Text("$gender")))
                            .toList(),


                      ),
                    ),
                  ],
                );
              }
            }
        ),
        ),
      ),
    ];

Any help would be appreciated.

Upvotes: 0

Views: 1527

Answers (2)

Romanoffa
Romanoffa

Reputation: 71

The working solution for the question. If there is any better way feel free to post :)

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';

class MyData {
  String title;
  String days;
  String words;
  String rep;
  String gender;
  var username;

  MyData(
      {this.gender, this.title, this.days, this.words, this.rep, this.username,
      });

}

class StepperBody extends StatefulWidget {
  @override
  _StepperBodyState createState() => _StepperBodyState();
}

class _StepperBodyState extends State<StepperBody> {
  int currStep = 0;
  static var _focusNode = FocusNode();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  Future<List<String>> _future;
  Future<List<String>> _getcar;

  List<GlobalKey<FormState>> formKeys = [
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>(),
    GlobalKey<FormState>()
  ];

  String _key = "786465659081B207EB5BF1EF9AF7552A6";
  String _api = "https://10.0.2.2/api/";

  Future<void> senddata() async {
    final response = await http.post(
        _api + "insert_data.php?key=" + _key, body: {
    });
    var resp = jsonDecode(response.body);
    print(resp.toString());
  }

  Future<List<String>> getData() async {
    var url = _api + "get_data.php?key=" + _key;
    http.Response response = await http.get(url);
    var resp = jsonDecode(response.body);
    print(resp.toString());
    return resp.map<String>((m) => m['username'] as String).toList();
  }

  Future<List<String>> getCar() async {
    var url = _api + "get_car.php?key=" + _key;
    http.Response response = await http.get(url);
    var resp = jsonDecode(response.body);
    print(resp.toString());
    return resp.map<String>((m) => m['plate'] as String).toList();
  }


  Widget getdis2(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: _getcar, // a previously-obtained Future<String> or null
      builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
        List<Widget> children;
        if (snapshot.hasData) {
          children = <Widget>[
            FormBuilderCheckboxList(
              decoration:
              InputDecoration(
                  labelText: "Languages you know"),
              attribute: "languages",
              initialValue: ["English"],
              options: snapshot.data
                  .map((gender) =>
                  FormBuilderFieldOption(
                      value: gender, child: Text("$gender")))
                  .toList(),
            ),
          ];
        } else if (snapshot.hasError) {
          children = <Widget>[
            Icon(
              Icons.error_outline,
              color: Colors.red,
              size: 60,
            ),
            Padding(
              padding: const EdgeInsets.only(top: 16),
              child: Text('Error: ${snapshot.error}'),
            )
          ];
        } else {
          children = <Widget>[
            SizedBox(
              child: CircularProgressIndicator(),
              width: 60,
              height: 60,
            ),
            const Padding(
              padding: EdgeInsets.only(top: 16),
              child: Text('Awaiting result...'),
            )
          ];
        }
        return Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: children,
          ),
        );
      },
    );

  }

  Widget getdis(BuildContext context) {
    return FutureBuilder<List<String>>(
        future: _future, // a previously-obtained Future<String> or null
        builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
          List<Widget> children;
          if (snapshot.hasData) {
            children = <Widget>[
              FormBuilderCheckboxList(
                decoration:
                InputDecoration(
                    labelText: "Languages you know"),
                attribute: "languages",
                initialValue: ["English"],
                options: snapshot.data
                    .map((gender) =>
                    FormBuilderFieldOption(
                        value: gender, child: Text("$gender")))
                    .toList(),
              ),
            ];
          } else if (snapshot.hasError) {
            children = <Widget>[
              Icon(
                Icons.error_outline,
                color: Colors.red,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Error: ${snapshot.error}'),
              )
            ];
          } else {
            children = <Widget>[
              SizedBox(
                child: CircularProgressIndicator(),
                width: 60,
                height: 60,
              ),
              const Padding(
                padding: EdgeInsets.only(top: 16),
                child: Text('Awaiting result...'),
              )
            ];
          }
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: children,
            ),
          );
        },
      );

  }

  @override
  void initState() {
    super.initState();
    _future = getData();
    _getcar = getCar();

    _focusNode.addListener(() {
      setState(() {});
      print('Has focus: $_focusNode.hasFocus');
    });
  }


  @override
  Widget build(BuildContext context) {
    void showSnackBarMessage(String message,
        [MaterialColor color = Colors.red]) {
      Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
    }

    void _submitDetails() {
      final FormState formState = _formKey.currentState;
      final FormBuilderState fbKeyState = _fbKey.currentState;
/*
      _fbKey.currentState.save();
      if (_fbKey.currentState.validate()) {
        print(_fbKey.currentState.value);
      }

 */
      if (!fbKeyState.validate()) {
        showSnackBarMessage('Please enter correct data');
        senddata();
      } else {
        showSnackBarMessage('Saved');
        formState.save();
        senddata();
        print("Name: ");


        _fbKey.currentState.save();
        if (_fbKey.currentState.validate()) {
          print(_fbKey.currentState.value);
        }
      }
    }


    final steps = [
      Step(
        title: const Text('Users'),
        //subtitle: const Text('Subtitle'),
        isActive: true,
        //state: StepState.editing,
        state: StepState.indexed,
        content: Form(
          key: formKeys[0],
          child: getdis(context),
        ),
      ),
      Step(
        title: const Text('Cars'),
        //subtitle: const Text('Subtitle'),
        isActive: true,
        //state: StepState.editing,
        state: StepState.indexed,
        content: Form(
          key: formKeys[1],
          child: getdis2(context),
        ),
      ),
    ];

    return Container(
        child: Form(
          key: _formKey,
          child: ListView(children: <Widget>[
            Stepper(
              steps: steps,
              physics: ClampingScrollPhysics(),
              type: StepperType.vertical,
              currentStep: this.currStep,
              onStepContinue: () {
                setState(() {
                  if (formKeys[currStep].currentState.validate()) {
                    if (currStep < steps.length - 1) {
                      currStep = currStep + 1;
                    } else {
                      currStep = 0;
                    }
                  }
                  // else {
                  // Scaffold
                  //     .of(context)
                  //     .showSnackBar( SnackBar(content:  Text('$currStep')));

                  // if (currStep == 1) {
                  //   print('First Step');
                  //   print('object' + FocusScope.of(context).toStringDeep());
                  // }

                  // }
                });
              },
              controlsBuilder: (BuildContext context,
                  {VoidCallback onStepContinue, VoidCallback onStepCancel}) {
                return Row(
                  //   mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    //
                    RaisedButton(
                      color: Colors.red,
                      child: Text("Forward",
                          style: TextStyle(color: Colors.white)),
                      onPressed: onStepContinue,
                    ),

                    SizedBox(width: 15,),
                    RaisedButton(
                      color: Colors.red,
                      child: Text(
                          "Back", style: TextStyle(color: Colors.white)),
                      onPressed: onStepCancel,
                    ),
                  ],
                );
              },
              onStepCancel: () {
                setState(() {
                  if (currStep > 0) {
                    currStep = currStep - 1;
                  } else {
                    currStep = 0;
                  }
                });
              },
              onStepTapped: (step) {
                setState(() {
                  currStep = step;
                });
              },
            ),

            RaisedButton(
              child: Text(
                'Save',
                style: TextStyle(color: Colors.white),
              ),
              onPressed: () {
                var submitDetails = _submitDetails;
                submitDetails();
              },
              color: Colors.lightGreen,
            ),
          ]),
        ));
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: "test",),
    );
  }
}

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

  final String title;

  @override
  MyAppScreenMode createState() => MyAppScreenMode();
}

class MyAppScreenMode extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        theme: new ThemeData(
          primarySwatch: Colors.red,
        ),
        home: new Scaffold(

          appBar: new AppBar(
            title: new Text('Test stepper'),
          ),
          body: new StepperBody(),

        ));
  }
}

Upvotes: 1

Taldorr
Taldorr

Reputation: 195

Im not sure about this, but in my understanding, a FutureBuilder expects exactly 1 future. the returned value of this future is accessable with "snapshot.data".

If you need to wait for multiple futures to resolve, I propose you use multiple FutureBuilders.

Another way would be to use Future.wait() somewhere else and return all required data as one Furure from there.

Upvotes: 0

Related Questions