Is there a way to make a FlutterFormBuilder with a Checkbox with data from Firestore?

Viewed 358

I have a problem that I haven't seen anywhere.

I have a basic collection of Entities in my Firestore, each one with a name. I would like to present those names as options of a Checkbox and I don't know if that is even possible. I will post here my code until now.

I have an EntityService to get the documents inside the collection


class EntityService{
  CollectionReference ref = FirebaseFirestore.instance.collection("Entities");
  EntityService();

  List<Entity> _EntitiesFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc){
      print(doc.data);
      return Entity(doc.id,doc.get('name')?? '');
    }).toList();
  }

  // get brews stream
  Stream<List<Entity>> get entities {
    return ref.snapshots()
        .map(_EntitiesFromSnapshot);
  }
...

I have the whole widget wrapped in a StreamProvider (I didn't come up with a better solution). Let's call it "form.dart".


class FormNewActivity extends StatefulWidget {
  @override
  _FormNewActivityState createState() => _FormNewActivityState();
}

class _FormNewActivityState extends State<FormNewActivity> {
  final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return StreamProvider<List<Entity>>.value(
      value: EntityService().entities,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Form"),
        ),
        body: FormBuilder(
          key: _fbKey,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: SingleChildScrollView(
              child: Column(
                children:[
                  FormElements(),
                  Padding(
                    padding: const EdgeInsets.symmetric(vertical: 16),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        RaisedButton(
                          child: Text("Create"),
                          onPressed: (){
                            if(_fbKey.currentState.saveAndValidate()){
                              ActivityService().addActivityMap(_fbKey.currentState.value);
                              Navigator.pop(context);
                            }
                          },
                        ),
                      ],
                    ),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

In "form.dart", I call FormElements() which is where is the CheckBox. The file is "form_elements.dart".

class FormElements extends StatefulWidget {
  @override
  _FormElementsState createState() => _FormElementsState();
}

class _FormElementsState extends State<FormElements> {

  List<String> EntitiesToNames(List<Entity> entitylist){
    List<String> namelist = new List();
    for (var i=0; i<entitylist.length; i++) {
      namelist.add(entitylist[i].name);
      print(namelist);
    }
    return namelist;
  }

  @override
  Widget build(BuildContext context) {
    final List<String> listOfEntities = EntitiesToNames(Provider.of<List<Entity>>(context) ?? []);
    return Container(
      color: Colors.white,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            Text('Titol',
                style: TextStyle(fontSize: 20, color: Colors.black)),
            //* ----------------------------------------------------
            //* TEXT INPUT
            //* ----------------------------------------------------
            FormBuilderTextField(
              maxLines: 1,
              obscureText: false,
              attribute: 'title',
              readOnly: false,
              validators: [
                FormBuilderValidators.required(),
              ],
            ),
            SizedBox(height: 20),
            Text('Descripcio',
                style: TextStyle(fontSize: 20, color: Colors.black)),
            //* ----------------------------------------------------
            //* TEXT INPUT
            //* ----------------------------------------------------
            FormBuilderTextField(
              maxLines: 10,
              obscureText: false,
              attribute: 'desc',
              readOnly: false,
              validators: [],
            ),
            SizedBox(height: 20),
            //* ----------------------------------------------------
            //* CHECKBOX GROUP
            //* ----------------------------------------------------
            Text('checkboxGroup',
                style: TextStyle(fontSize: 20, color: Colors.black)),
            FormBuilderCheckboxGroup(
              attribute: 'checkboxGroup',
              options: [
                FormBuilderFieldOption(value: listOfEntities[0]),
                FormBuilderFieldOption(value: listOfEntities[1]),
                FormBuilderFieldOption(value: listOfEntities[2]),
                // ...
              ],
            ),
            SizedBox(height: 20),
          ],
        ),
      ),
    );
  }
}

I would like to cycle through the values in List<String> listOfEntities and create a FormBuilderFieldOption for each of the values in the list.

Hope is not too difficult to read.

1 Answers

I answered my own question, the problem is solved with this code.

class FormElements extends StatefulWidget {
  @override
  _FormElementsState createState() => _FormElementsState();
}

class _FormElementsState extends State<FormElements> {

  List<String> EntitiesToNames(List<Entity> entitylist){
    List<String> namelist = new List();
    for (var i=0; i<entitylist.length; i++) {
      namelist.add(entitylist[i].name);
      print(namelist);
    }
    return namelist;
  }

  @override
  Widget build(BuildContext context) {
    final List<String> listOfEntities = EntitiesToNames(Provider.of<List<Entity>>(context) ?? []);
    return Container(
      color: Colors.white,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            Text('Titol',
                style: TextStyle(fontSize: 20, color: Colors.black)),
            //* ----------------------------------------------------
            //* TEXT INPUT
            //* ----------------------------------------------------
            FormBuilderTextField(
              maxLines: 1,
              obscureText: false,
              attribute: 'title',
              readOnly: false,
              validators: [
                FormBuilderValidators.required(),
              ],
            ),
            SizedBox(height: 20),
            Text('Descripcio',
                style: TextStyle(fontSize: 20, color: Colors.black)),
            //* ----------------------------------------------------
            //* TEXT INPUT
            //* ----------------------------------------------------
            FormBuilderTextField(
              maxLines: 10,
              obscureText: false,
              attribute: 'desc',
              readOnly: false,
              validators: [],
            ),
            SizedBox(height: 20),
            //* ----------------------------------------------------
            //* CHECKBOX GROUP
            //* ----------------------------------------------------
            Text('checkboxGroup',
                style: TextStyle(fontSize: 20, color: Colors.black)),
            FormBuilderCheckboxGroup(
              attribute: 'checkboxGroup',
              options:
                listOfEntities.map((e) => FormBuilderFieldOption(value: e)).toList(),
            ),
            SizedBox(height: 20),
          ],
        ),
      ),
    );
  }
}
Related