gantonioid
gantonioid

Reputation: 457

Get values of dynamic list of widgets - flutter

I've managed to make a dynamic questionnaire connecting flutter with Firestore.

My custom Question widgets are just a Text() holding the string of the question, and a Slider() so the user can give an answer from 1 to 5

Now that the questions are displayed, how should I get the values?

Here's my code:

var questions = <Widget>[];

//Async read to the DB
Future query() async {
  var snap = await Firestore.instance
    .collection("Forms")
    .document(formID)
    .get();

  var arr = <Widget>[]; //just a temp holder of the widgets
  for(String q in list){
    arr.add(Question(min: 1.0, max: 5.0, question: q, value: 1.0,));
  }

  setState(() {
    questions = arr;
  });
}

And then in the build I'm rendering:

Scaffold(
  body:Container(
    child:Column(
      children: <Widget>[
        Text("Title"),
        Column(
          children: questions,
        ),
        RaisedButton(
          onPressed: () => sendFeedback(),
          color: Colors.redAccent,
          textColor: Colors.white,
          child: Text("Send")
      ]
    )

What would be the code for the sendFeedback() function? I would like to get the values for all the sliders in my children list and then write those to Firestore in only one call to the DB.

Upvotes: 4

Views: 2396

Answers (2)

gantonioid
gantonioid

Reputation: 457

For the purpose of this app, it's enough to have a global variable

Map<String, double> responses = Map();

that is reset when I navigate into a questionnaire, and then each Slider has to update the Map like so (onChange):

Slider(
  value: value,
  min: widget.min,
  max: widget.max,
  divisions: (widget.max - 1).round(),
  label: value.ceil().toString(),
  activeColor: color,
  onChanged: (double val1) {
     //Force a re-render
     setState(() {
       //Update the value of the Slider
       value = val1;
       //Do some operations, assign a color based on the result
       double p = value / widget.max;
       if (p > 0 && p <= 0.3) {
         color = Colors.red;
       } else if (p > 0.3 && p <= 0.6) {
         color = Colors.orangeAccent;
       } else {
         color = Colors.green;
       }
       //Update the value of the parent Widget
       widget.value = value;
       ratings[widget.question] = value;

       //Done, print in console for debugging
       print(value);
     });
   })

I invested quite some time into the BLoC pattern, but I couldn't make it work as expected. Maybe I'll try it again soon and post back the solution.

Upvotes: 0

Sebastian
Sebastian

Reputation: 3894

You need to hold the state of all sliders. I'd recommend you the BLoC pattern for state management.

You can read about it here

Edit: You can have a List<int> to hold the values in your bloc and in every slider you will implement the function onChangeEnd: bloc.addValue and send the slider value to the bloc which will add them to the list. Then on the button you will have something like this onPressed: () => bloc.sendFeedback() that will take the values from the list and write them to Firestore.

Keep in mind that this is a solution on the top of my head right now for you to understand the concept

Upvotes: 1

Related Questions