Search code examples
flutterlistdartdictionarywidget

How to dynamically execute list.map inside a Widget (Dart/Flutter)


I'm trying to dynamically add lines to a widget that would change depending on how many elements an array holds.

However, I run into the following error over the second list operator (everything inside the for-loop): The element type 'Set<_ExerData>' can't be assigned to the list type 'Widget'

Does anyone have a solution to this? Here is the block of code it is being executed in:

Flexible(
  child: Column(
    children: [                              
      ...[
        ExerTitle(title, leftEdgeInset, 112),
      ]
        .map((menu) => _ExerTitle(
          title: menu.title,
          leftEdgeInset: menu.leftEdgeInset,
          time: menu.time,
        )),
              
      for (int i = 0; i < exerArr.length; i++) {
      ...[
        ExerData(exerArr[i], setsArr[i], leftEdgeInset),
      ]
        .map((menu) => _ExerData(
          exer: menu.exer,
          sets: menu.sets,
          leftEdgeInset: menu.leftEdgeInset,
        )),
      }
    ],
  ),
),

This block of code is inside a container and should display a data for each iteration from 'ExerData' inside the Column()


Solution

  • The error you're getting is due to the fact that you're trying to "spread" a Set<_ExerData> into a List<Widget>, the error you got is pretty clear about that. But what's not clear is where that Set is coming from because you're making a "grammar" mistake, basically, in your Dart code.

    The syntax:

    [...foo]
    

    is for spreading the value of a collection foo inside the List being created with square brackets.

    Inside a literal List, you can also use "for-collection"s:

    void main() {
      const mySet = {'abc', 'def'};
      final list = ['hi', for (final v in mySet) '\n* $v'];
      print(list.join());
    }
    

    This prints:

    hi
    * abc
    * def
    

    In your code, you're mixing up things... first, you're using both the spread operator and collection-for... but you're also trying to collect Sets in your collection-for, which I believe is a misunderstanding on your part about collection-fors.

    This code should illustrate the problem:

    void main() {
      print([for (final v in [1, 2, 3]) { v }]);
    }
    

    This will print:

    [{1}, {2}, {3}]
    

    Each value of the list got wrapped into a Set because collection-for expressions do not take a block, only for-loops do! So curly-braces inside a collection-for are just literal Sets.

    In the example above, {1} is a Set containing the element 1.

    I am not sure why you're mapping over a single-element List as that's just not necessary assuming you only have one element... but if we keep that mapping (assuming you may add more items in the future??) the code should look something like this:

      final widgets = [
        ...[
          ExerTitle(title, leftEdgeInset, 112),
        ].map((menu) => _ExerTitle(
              title: menu.title,
              leftEdgeInset: menu.leftEdgeInset,
              time: menu.time,
            )),
        for (int i = 0; i < exerArr.length; i++)
          ...[
            ExerData(exerArr[i], setsArr[i]),
          ].map((menu) => _ExerData(
                exer: menu.exer,
                sets: menu.sets,
              ))
      ];