In your views you often want to only conditionally show something, or loop through a list of items. For this flutter-view has some intentionally simple flow control keywords.
This will only render the widget if the passed condition is true.
{% tabs %} {% tab title="Pug" %}
user-profile(flutter-view :user[User])
.user
.name ${user.name}
.company(if='user.company != null') Works at ${user.company}
{% endtab %}
{% tab title="generated Dart" %}
UserProfile({required User user}) {
return Container(
child: Column(
children: [
Container(
child: Text('${user.name}'),
),
user.company != null ?
Container(
child: Text('Works at ${user.company}'),
)
: SizedBox(),
],
),
);
}
// left out some flatten operations for simplicity
{% endtab %} {% endtabs %}
In the above example, the company will only be shown if the passed user has the company property set.
This will only render the widget if the passed condition is false, otherwise it returns null.
With type and null-safety in Dart, you sometimes need to either pass an argument or null. The normal if
above will return a SizedBox()
if the condition fails. For building widget trees, this is usually makes sense. However sometimes we need to pass an argument that can be null, depending on a condition. In these edge cases, use if-null.
{% tabs %} {% tab title="Pug" %}
app-bar
.title(as='title' null-if='user.name == null') ${user.name}
{% endtab %}
{% tab title="generated Dart" %}
PlatformAppBar(
title: !(name == null) ?
Container(
child: Text(
'${name}',
),
) : null,
)
{% endtab %} {% endtabs %}
In the above example, the title of the AppBar
widget will be set to null if the user.name
is null
.
A slot is a placeholder for a value. It will take the value of the first valid child. Alternatively, you can also directly pass a value into it:
{% tabs %} {% tab title="Pug" %}
wrapper(flutter-view :content[Widget])
slot(:value='content').content
.footer A footer
{% endtab %}
{% tab title="Generated Dart" %}
Column Wrapper({ required Widget content }) {
return Column(
children: __flatten([
content,
//-- FOOTER ----------------------------------------------------------
Container(
child: Text(
'A footer',
),
)
]),
);
}
{% endtab %} {% endtabs %}
Slot can function as an if/else. In the next example you see either the .status being shown, or the .empty.
{% tabs %} {% tab title="Pug" %}
tasks-page(flutter-view :tasks[List])
scaffold
slot(as='body')
.status(if='tasks.isNotEmpty') You have ${tasks.length} tasks
.empty You have no tasks yet...
{% endtab %}
{% tab title="generated Dart" %}
Scaffold TasksPage({ required List tasks }) {
return Scaffold(
body: (tasks.isNotEmpty) ?
//-- STATUS ----------------------------------------------------------
Container(
child: Text(
'You have ${tasks.length} tasks',
),
):
true ?
//-- EMPTY ----------------------------------------------------------
Container(
child: Text(
'You have no tasks yet...',
),
)
: Container(),
);
}
{% endtab %} {% endtabs %}
As you can see in the above example, you can use the as property to assign the slot value to a parameter as well. In this case, the content of the slot is placed in the body parameter of the Scaffold.
By adding multiple children with if to a slot, you can also create a switch/case:
{% tabs %} {% tab title="Pug" %}
slot
.apple(if='fruit=="Apple"')
.pear(if='fruit=="Pear"')
.peach(if='fruit=="Peach"')
.unknown // the fallback
{% endtab %} {% endtabs %}
Use for to repeat a widget for every value in a list. For every repetition, the value gets assigned to a variable, which you can use to render the widget and its children.
{% tabs %} {% tab title="Pug" %}
tasks-page(flutter-view :tasks[List])
scaffold
slot(as='body')
.task(for='task in tasks')
.title ${task.title}
.description ${task.description}
{% endtab %}
{% tab title="generated Dart" %}
Scaffold TasksPage({ required List tasks }) {
return Scaffold(
body:
//-- BODY ----------------------------------------------------------
Container(
child: (tasks as List).map((task) {
return
//-- TASK ----------------------------------------------------------
Container(
child: Column(
children: [
//-- TITLE ----------------------------------------------------------
Container(
child: Text(
'${task.title}',
),
),
//-- DESCRIPTION ----------------------------------------------------------
Container(
child: Text(
'${task.description}',
),
)
]),
),
);
}).toList(),
),
);
}
{% endtab %} {% endtabs %}
You can also get the index (starting at 0) of the current entry as such:
.task(for='task, index in tasks')