How do I map a list of potentially null widgets? - flutter

I'm new to Flutter and haven't found much success in my brief online search for an answer to this, which is the reason for this post.
Here's the code in question:
// `myList` can potentially be null.
children: widget.myList?.map((item) {
return Text("Hi.");
}).toList(),
I'm trying to loop over a List<String>? of errors in my stateful widget, inside of the children: property of a Column.
Dart is telling me that I cannot map over a List<String>?, and suggests that I use myList?.map instead.
However, when I do that, the issue now becomes that children: expects a List<Widget> and can therefore not accept a List<Widget>? ...
I seem to be stuck in circuitous errors, but somehow I feel the solution is simple. I'm still learning about null-safety.
So tl;dr:
How do I reconcile between a potentially null list of widgets, and a property that expects a list of widgets that isn't null?
Solution
children: myList?.map((e) => Text(e)).toList() ?? [],

If your List is List<Widget>?, you can add simply a null check like so:
children: _widgets?.map((item) => item).toList() ?? [Text('List was null')],
If your List is List<Widget?>? you can change it to:
children: _widgets?.map((item) => item ?? Text('widget was null')).toList() ?? [Text('List was null')],
If you want to map a List<String?> inside a Column
Column(
children: _strings.map((e) => Text(e ?? 'String was null')).toList(),
)
OR
Column(
children: _strings.map((e) => e == null ? Text('was null') : Text(e)).toList(),
)
If your List is List<String>?
Column(
children: _strings?.map((e) =>Text(e)).toList() ?? [Text('The list was null')],
)

Related

How to display a column when a variable is true in Flutter?

I keep getting this error that res is not defined, so I am trying to figure out how to run the column code after res is defined like in js you can do {res && (code)}.
Column(
children: res['rooms'].map((r) => Card(
'name',
'${r['messages'][r['messages'].length - 1]['content']}',
'${r['_id']}'
)),
),
You can check if your res variable is equal to null.
This is the non nullable approach to your problem, but you should check to migrate your project to null safety to avoid all those null checks.
res == null
? Column(
children: res['rooms'].map((r) => Card(
'name',
'${r['messages'][r['messages'].length - 1]['content']}',
'${r['_id']}')),
)
: Container(),
It can be hard to read ternary expressions sometimes if you have a large widget within a expression. It also requires you to provide an "else" widget.
I approach this with the spread operator, with a single if statement
Column(
children: <Widget>[
if (res != null)
...res.map((r) => Card(
'name',
'${r['messages'][r['messages'].length - 1]['content']}',
'${r['_id']}')),
],
)
Simple use ternary login like this -
Container(
child: res != null
? Column(
children: []
)
: SizedBox() //Use SizedBox instead of Container for better efficiency
)
And update the UI again once "res" is populated.

Return a list of widgets in Flutter

Column(
children: <Widget>[
...myObject
.map((data) => Text("Text 1"), Text("Text 2")),
]
);
This block of code will fail because I'm returning 2 widgets instead of one. How could I fix it and return as many widget as I want without creating another column inside the map?
First you cant use an arrow function to return multiple values, you need to change it to a normal function that returns a list of widgets. Second, you need to use the .toList() method since .map is lazy and you need to iterate in order to map execute.
With this 2 steps you are going to end with a List<List<Widget>> and you should flat it before return it to a column that needs a List<Widget>. This can be achieved with the Iterable.expand() with an identity function.
You can try something like this:
Column(
children: <Widget>[
..._generateChildrens(myObjects),
],
),
And the actual implementation to obtain the widgets is:
List<Widget> _generateChildrens(List myObjects) {
var list = myObjects.map<List<Widget>>(
(data) {
var widgetList = <Widget>[];
widgetList.add(Text("Text 1"));
widgetList.add(Text("Text 2"));
return widgetList;
},
).toList();
var flat = list.expand((i) => i).toList();
return flat;
}
Hope it helps!

How to use the children: <Widget> of a Row to display a list of Icons [duplicate]

This question already has answers here:
How to return part of a list of Widgets in Flutter
(3 answers)
Closed 3 years ago.
I am pretty new to Flutter development and I'm trying to pass a List to a Row using the children : <Widget>[] since I want to add something else beside the list in the future.
I know that this feature only accepts Widgets and maybe I have to convert my list to a Widget in someway ?
Any hints or tips on how to get it to work is appreciated :)
This is working.
List<Icon> scoreKeeper = [];
Row(
children: scoreKeeper,
),
This is not.
I get this error: The element type 'List' can't be assigned to the list type 'Widget'.
List<Icon> scoreKeeper = [];
Row(
children : <Widget>[
scoreKeeper,
],
),
You can use the spread operator (...) from Dart 2.3 which will spread the list of, in this case, Icons and it will work.
List<Icon> scoreKeeper = [];
Row(
children : <Widget>[
...scoreKeeper,
],
),

Meaning of Triple Dots [...] in Flutter Syntax

Can someone please clarify what is the meaning and usage of "..." in Flutter?
I wanted to learn about "triple dots" used in Flutter syntax. After some reading I found out that the word I was looking for was "spreading".
Widget _build() {
List<Widget> children = [
Text("first child"),
Text("second child"),
Text("third child"),
];
return Column(
children: <Widget>[
...children,
Text("fourth child"),
],
);
}
If I didn't have the ... right before the children, it will give an error The element type 'List<Widget>' can't be assigned to the list type 'Widget'.
I just thought that someone should post a question about it. What is "..." in flutter syntax? What does it mean?
Dart 2.3 introduced the spread operator (...) and the null-aware spread operator (...?), which provide a concise way to insert multiple elements into a collection.
For example, you can use the spread operator (...) to insert all the elements of a list into another list:
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
If the expression to the right of the spread operator might be null, you can avoid exceptions by using a null-aware spread operator (...?):
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
For more details and examples of using the spread operator, see the spread operator proposal.
I used to have this problem. I solved this problem by adding .toList(); to the List Widget.
Widget _build() {
List<Widget> children = [
Text("first child"),
Text("second child"),
Text("third child"),
].toList();
return Column(
children: <Widget>[
...children,
Text("fourth child"),
],
);
}
Hope it helps
spread operator (...) is used to provide a way to assign values to Collections, more commonly it found inside the column to render its child.
List<String> values = ['one', 'two', 'three'];
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
...values.map((value) {
return Text(value);
}),
],
),
),
);
Output:

flutter get value from object and display in Text()

How to get value from an object in flutter? i need to display name of products in Text()
List<Object> _dataResponse = [
{"item":"chakka"},
{"item":"manga"},
{"item":"thenga"},
];
ListView(
children: _productName
.map((f) => ListTile(
leading: Icon(Icons.check_circle,color: Colors.green,),
title: **Text('$f["item"]')**,
))
.toList(),
)
For complex expressions (not just simple identifiers) you need to use ${...} instead of $...
Text('${f["item"]}')