Creating widget layouts

Last updated 2 months ago

Overview

In Flutter, widget trees are built by passing a child or children. Widget trees have a lot of indentation, especially since in Flutter nearly everything is a widget, and composition is preferred to inheritance. This can lead to complex nesting and child parameters.

Flutter-views are optimised for building widget trees. Pug in particular is well suited for creating tree structures and moving parts around.

The following example generates a Dart method FooPage(), which returns a Scaffold with an AppBar, and a centralized greeting message.

The Pug creates the layout, and the main.dart file uses this layout to render the app. This separation between layout and logic is fundamental to using flutter-view.

Pug

generated Dart

main.dart

foo-page.pug

foo-page(flutter-view:greeting)

scaffold

app-bar(as='appBar')

container(as='title') Foo Page

center(as='body') Hello $greeting!

foo-page.dart

FooPage({@required greeting}){

returnScaffold(

appBar:AppBar(

title:Container(

child:Text('Foo page'),

),

),

body:Center(

child:Text('Hello $greeting!'),

),

);

}

main.dart

import'package:flutter/material.dart';

import'foo-page.dart';

​

voidmain()=>runApp(TestApp());

​

classTestAppextendsStatelessWidget{

​

@override

Widget build(BuildContext context){

returnMaterialApp(

title:'Test App',
home:FooPage(greeting:'world!')

);

}

​

}

Adding children to widgets

In a flutter-view, add indented child tags to tags to automatically have them assigned as child or children parameters.

In flutter-view Pug/HTML content, an HTML tag is a method or constructor call, and its parameters are parameters for this method or constructor. The tag children are assigned as the Flutter child/children parameters.

To see how this works, compare the Pug and generated Dart code in this example:

Pug

generated Dart

container

column

row

text(:value='first row!')

row

text(:value='second row!')

row

flat-button

text(:value='Click me!')

returnContainer(

child:Column(

children:[

Row(

children:[

Text('first row!'),

],

),

Row(

children:[

Text('second row!'),

],

Row(

FlatButton(

child:Text('Click me!'),

)

),

],

),

);

Automatic columns

Flutter-view knows which classes generally need children instead of single child, and automatically creates Columns when you pass multiple children. Also, if you pass text, flutter-view it automatically wraps it in a Text widget as well. This together allows you to be more terse:

Calling dart factory constructors

Some Flutter Dart classes may use factory constructors. For example, ButtonTheme has a ButtonTheme.bar() constructor.

To call the factory constructor instead of the default constructor, pass the constructor after the class name, separated with a colon.

Pug

generated Dart

button-theme:bar

| some content here

ButtonTheme.bar(

child:Text(

'some content here'

),

)

Passing children instead of child

There may be cases where flutter-view does not recognise your tag needs a children parameter instead of a child parameter. In that case use and array and assign it as children:

Pug

generated Dart

column

array(as='children')

row first!

row second!

Column(

children:[

Row(

children:[

Text('first!'),

]

),

Row(

children:[

Text('second!'),

]

),

]

)

Passing const widgets

For optimising performance, you may want to pass some widgets as constants. You can do this by adding a const parameter in a widget:

To see how this works, compare the Pug and generated Dart code in this example:

Pug

generated Dart

container

column(const)

row

text(:value='first row!')

returnContainer(

child:constColumn(

children:[

Row(

children:[

Text('first row!'),

],

),

],

),

);

Passing parameters

To pass parameters besides child or children, you pass them as pug/html parameters.

String parameters

You can pass strings by using quotes. Both double and single quotes work.

For example:

Pug

generated Dart

banner(title='testing')

| Hello world!

returnBanner(

title:'testing',

child:Text('Hello world!'),

);

Expression parameters

To assign a Dart expression as the value of a parameter:

start the parameter name with :

wrap the expression in quotes. You may need to escape strings.

For example:

Pug

generated Dart

flat-button(:color='highlighted ? Colors.red : Colors.grey')

| Click me!

returnFlatButton(

color: highlighted ? Colors.red : Colors.grey,

child:Text('Click me!'),

);

For title we want to pass a direct string, but for color we want to pass a value by reference, so we add : in front of the parameter.

Unnamed parameters

Some widgets take an unnamed parameter in their constructor. You can pass this using the reserved value parameter:

Pug

generated Dart

container

icon(:value='Icons.add')

text(value='Hello world')

returnContainer(

child:Column(

children:[

Icon(Icons.add),

Text('Hello world'),

]

),

);

Escaping parameter names

You may need to pass a parameter that has the name of a reserved keyword, such as value. You can bypass this problem by escaping your parameter with the ^ sign:

:^value='foo'

Passing complex parameter values

Sometimes what you want to pass is not just a single value, but a value that is constructed of many widgets. To solve this, you may take a child and use the as keyword to assign it as a parameter to the parent widget.

Pug

generated Dart

scaffold

app-bar(as='appBar')

container(as='title') Test App

center(as='body') Hello world!

returnScaffold(

appBar:AppBar(

title:Container(

child:Text('Test App'),

),

body:Center(

child:Text('Hello world!'),

),

),

);

The Scaffold class used above has no child or children parameters. Instead we add two children and assign them as parameters using the as property.