Lesson 12 min

Collection If & Collection For

00:00 / 00:00

Collection If & Collection For

One of Dart's most distinctive and powerful features is the ability to use control flow directly inside collection literals. You can conditionally include elements and loop inline — all within [], {}, or <> brackets. This makes building dynamic lists and maps dramatically cleaner, especially in Flutter.


🔹 What Are Collection Operators?

Traditional approach to building a list dynamically:

dart
void main() { bool showBonus = true; List<String> items = ['Apple', 'Banana']; if (showBonus) { items.add('Cherry'); } print(items); // [Apple, Banana, Cherry] }

With collection if, you can do this inline:

dart
void main() { bool showBonus = true; List<String> items = [ 'Apple', 'Banana', if (showBonus) 'Cherry', ]; print(items); // [Apple, Banana, Cherry] }

The list builds itself based on the condition — no mutation needed!


🔹 Collection If

Syntax:

dart
[ element1, if (condition) elementIfTrue, element2, ]

With else

dart
void main() { bool isPremium = false; List<String> menuItems = [ 'Home', 'Profile', if (isPremium) 'Premium Dashboard' else 'Upgrade to Premium', 'Settings', 'Logout', ]; print(menuItems); // [Home, Profile, Upgrade to Premium, Settings, Logout] }

Multiple Conditional Elements

dart
void main() { bool isAdmin = true; bool isDeveloper = false; List<String> permissions = [ 'read', 'write', if (isAdmin) 'delete', if (isAdmin) 'manage_users', if (isDeveloper) 'access_logs', if (isDeveloper) 'run_migrations', ]; print(permissions); // [read, write, delete, manage_users] }

Collection If with Maps and Sets

Collection if works with all collection types:

dart
void main() { bool includeEmail = true; // Map with conditional entry Map<String, String> userInfo = { 'name': 'Alice', 'phone': '+91-9876543210', if (includeEmail) 'email': 'alice@example.com', }; print(userInfo); // {name: Alice, phone: +91-9876543210, email: alice@example.com} // Set with conditional element bool hasProBadge = true; Set<String> badges = { 'member', 'active', if (hasProBadge) 'pro', }; print(badges); // {member, active, pro} }

🔹 Collection For

Syntax:

dart
[ for (var item in iterable) expression, ]

Transform every element of an iterable inline — like a concise version of .map():

dart
void main() { List<int> numbers = [1, 2, 3, 4, 5]; // Double every number List<int> doubled = [ for (var n in numbers) n * 2, ]; print(doubled); // [2, 4, 6, 8, 10] }

Equivalent of a Traditional for Loop

dart
void main() { // Traditional List<String> labels1 = []; for (int i = 1; i <= 5; i++) { labels1.add('Item $i'); } // Collection for List<String> labels2 = [ for (int i = 1; i <= 5; i++) 'Item $i', ]; print(labels1); // [Item 1, Item 2, Item 3, Item 4, Item 5] print(labels2); // [Item 1, Item 2, Item 3, Item 4, Item 5] }

Collection For with Maps

dart
void main() { List<String> fruits = ['Apple', 'Banana', 'Cherry']; // Create a Map from a List Map<String, int> fruitLengths = { for (var fruit in fruits) fruit: fruit.length, }; print(fruitLengths); // {Apple: 5, Banana: 6, Cherry: 6} }

🔹 Combining Collection If and Collection For

The real power comes from combining them:

dart
void main() { List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Include only even numbers, squared List<int> evenSquares = [ for (var n in numbers) if (n % 2 == 0) n * n, ]; print(evenSquares); // [4, 16, 36, 64, 100] }
dart
void main() { List<String> allUsers = ['Alice', 'Bob', 'Charlie', 'Dave']; List<String> blockedUsers = ['Bob']; // Build a list excluding blocked users List<String> activeUsers = [ for (var user in allUsers) if (!blockedUsers.contains(user)) user, ]; print(activeUsers); // [Alice, Charlie, Dave] }

🔹 Spread Operator ...

The spread operator inserts all elements of a collection into another:

dart
void main() { List<int> list1 = [1, 2, 3]; List<int> list2 = [4, 5, 6]; // Merge two lists List<int> merged = [...list1, ...list2]; print(merged); // [1, 2, 3, 4, 5, 6] // Insert in the middle List<int> extended = [0, ...list1, 99, ...list2, 100]; print(extended); // [0, 1, 2, 3, 99, 4, 5, 6, 100] }

Null-Aware Spread ...?

Use ...? when the list might be null — it safely spreads nothing if the value is null:

dart
void main() { List<String>? extraItems; // null List<String> menu = [ 'Home', 'Profile', ...?extraItems, // safely ignored when null 'Logout', ]; print(menu); // [Home, Profile, Logout] // Now with a value extraItems = ['Settings', 'Help']; List<String> menu2 = [ 'Home', 'Profile', ...?extraItems, 'Logout', ]; print(menu2); // [Home, Profile, Settings, Help, Logout] }

🔹 Why These Are Powerful in Flutter

In Flutter, your entire UI is built from nested expressions. Collection operators fit perfectly because they let you write clean, conditional widget lists without breaking out of the expression tree.

Without Collection If (messy):

dart
// Flutter preview List<Widget> buildItems(bool isLoggedIn) { List<Widget> items = [ const ListTile(title: Text('Home')), const ListTile(title: Text('About')), ]; if (isLoggedIn) { items.add(const ListTile(title: Text('Dashboard'))); items.add(const ListTile(title: Text('Logout'))); } else { items.add(const ListTile(title: Text('Login'))); } return items; }

With Collection If (clean):

dart
// Flutter preview List<Widget> buildItems(bool isLoggedIn) => [ const ListTile(title: Text('Home')), const ListTile(title: Text('About')), if (isLoggedIn) ...[ const ListTile(title: Text('Dashboard')), const ListTile(title: Text('Logout')), ] else const ListTile(title: Text('Login')), ];

Tip: You can combine if with ... spread to conditionally add multiple widgets at once: if (condition) ...[widget1, widget2]


🔹 Real-World Examples

Example 1: Building a Shopping Cart

dart
void main() { List<Map<String, dynamic>> cartItems = [ {'name': 'Laptop', 'price': 999.99}, {'name': 'Mouse', 'price': 29.99}, {'name': 'Keyboard', 'price': 79.99}, ]; bool hasCoupon = true; double discount = 50.0; List<String> receipt = [ '=== RECEIPT ===', for (var item in cartItems) '${item['name']}: \$${item['price']}', if (hasCoupon) 'Coupon Discount: -\$$discount', '===============', ]; receipt.forEach(print); }

Output:

=== RECEIPT ===
Laptop: $999.99
Mouse: $29.99
Keyboard: $79.99
Coupon Discount: -$50.0
===============

Example 2: Flattening Nested Lists

dart
void main() { List<List<int>> matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ]; // Flatten the matrix into a single list List<int> flat = [ for (var row in matrix) for (var value in row) value, ]; print(flat); // [1, 2, 3, 4, 5, 6, 7, 8, 9] }

Example 3: Dynamic Navigation Menu

dart
void main() { bool isAdmin = true; bool isVerified = true; List<String> navItems = [ 'Home', 'Browse', if (isVerified) 'My Orders', if (isVerified) 'Profile', if (isAdmin) ...['Admin Panel', 'User Management', 'Reports'], 'Help', 'Logout', ]; navItems.forEach(print); }

Summary

FeatureSyntaxPurpose
Collection if[if (cond) element]Conditionally include an element
Collection if-else[if (cond) a else b]Choose between two elements
Collection for (for-in)[for (var x in list) expr]Transform/iterate inline
Collection for (classic)[for (int i=0; i<n; i++) expr]Build with index inline
Spread[...list]Insert all elements of a list
Null-aware spread[...?nullableList]Safely spread a nullable list

These collection operators are one of Dart's most elegant features. They reduce boilerplate, improve readability, and are essential for clean Flutter UI code. Up next: loops — for, while, and do-while!

WhatsApp