The
Web UI package
provides the tools and Dart code
that implement data binding, web components,
templates, and encapsulation.
To use these Web UI features,
you need to install the Web UI package in each application that uses it
and compile the project using the Web UI compiler.
To streamline the development process,
you can use Dart Editor to help set up your project,
install the package, and automate the build process.
This target begins by showing you how to set up a project to use Web UI,
including how to install the package.
(If you are unfamiliar with packages, the previous target,
Install Shared Packages,
has details.)
Then this target describes how to use two features of the Web UI package.
Specifically, you will learn
how to use data binding to embed mutable Dart data in your HTML page
and to declaratively attach event handlers to UI elements.
The next two targets,
Target 7: Use <template>
and
Target 8: Define a Custom DOM Tag,
describe other features of the Web UI package.
About using the Web UI package
You can use Web UI features directly in your HTML code
as naturally as you use standard HTML.
In fact, some of the Web UI syntax looks like regular HTML tags,
so you could think of the Web UI library as extending the HTML language.
Before you can run an app that uses Web UI,
you must compile the app using the Web UI compiler dwc.
The compiler translates the Web UI code
into standard HTML and Dart scripts
and includes the code that implements the Web UI features.
You run the compiled version of the app as you normally would
using the Dart VM or by converting it to JavaScript.

In this way,
Web UI provides an extra
layer between your code and the browser platform,
seamlessly providing you with new browser features like
web components and templates.
You can set up Dart Editor to automate the compilation process
for projects that use the Web UI library.
Dart Editor detects changes to your project files
and automatically compiles in the background.
With Dart Editor at the center of your development cycle,
you can create, edit, compile, and run your application
with Web UI quickly and easily.
Create a new application with Web UI installed
The easiest way to begin using the Web UI package
is to create a new application in Dart Editor.
-
In Dart Editor,
create a new project using File > New Application.
In the window that appears,
select Generate sample content and
in the list beneath it,
select
Web application (using the web_ui library).
Call the project webui_click_counter.

-
Dart Editor creates a directory
and the source files for your project.
Dart Editor also automatically runs pub install
to resolve the package dependencies
and install all of the necessary packages including the Web UI package.
Finally, Dart Editor builds the project—that is,
it compiles the application code
together with the Web UI library code—
and puts the final version in the out directory.

-
Select webui_click_counter.html and click the Run button
.
The app uses the custom element and data binding
features from the Web UI package to
implement the button and display the number of clicks.
-
You can use this sample application as the basis for your
Web UI application.
Install the Web UI package in an existing Web application
If you already have an application to which you would like to add Web UI,
you need to set up the package dependencies
and install the Web UI package libraries into your project.
This section assumes that you have read
the previous target,
Install Shared Packages,
and are familiar with the process
of installing packages.
-
In Dart Editor,
open an existing project.
For the example here,
we’re using the default sample application
generated by Dart Editor
when you create a new web application
without Web UI support.
Later in this target,
you will modify this application to use
data binding—a feature necessary to web components and templates.

-
Open the pubspec.yaml file, which is
in the top-level directory of your project.
By default,
Dart Editor displays the Overview panel,
which provides a handy UI for viewing and modifying the pubspec file.
You can use the Source
tab at the bottom of the window to view
the pubspec.yaml source code.
-
Add the Web UI package to the list of dependencies
by adding the Web UI package name,
web_ui, to the list.
Click Add… in the Overview panel,
or add the package name
to the dependencies list directly in the pubspec.yaml source.
YAML is whitespace-sensitive
so take care to indent the package name as shown:

-
Select pubspec.yaml, and install the package by
choosing Tools > Pub Install from the menu.
This recursively installs the web_ui package
and all the packages that it depends on.
The diagram below shows the file hierarchy for your application
after the package installation:

-
In the littleben sample,
the application files are in a directory called web.
To run the app, select the main host HTML file,
web/littleben.html,
and click the Run button
.
Set up background compilation in Dart Editor
Applications that use features from the Web UI package must be compiled.
You can set up Dart Editor to automatically compile
your project when any of its files change.
Once you have background compilation set up,
your edit/refresh/test cycle within Dart Editor will be quick and easy.
-
Create a file called build.dart in the same directory as pubspec.yaml.
In this case, that’s the project’s top-level directory.
Replace the auto-generated code with the following:
import 'package:web_ui/component_build.dart';
import 'dart:io';
void main() {
build(new Options().arguments, ['web/littleben.html']);
}
build.dart refers to the application’s primary HTML file web/littleben.html.
The pathname is specified relative to the build.dart file.

-
Make sure build.dart is selected and click
.
After a beat, a directory named out appears under the web directory.

Your project is now set up for background compilation.
Every time Dart Editor detects that you changed a file in your project,
it uses the Web UI compiler
to compile your project and update the files in web/out.
Generally speaking you can ignore the files in the web/out directory.
When you run your app,
Dart Editor runs these files automatically.
-
Run your app as you normally would:
select the original HTML file, web/littleben.html,
and click the Run button
.
Dart Editor runs the generated file in the web/out directory.

With background compilation set up in Dart Editor,
you can be certain that you are always running
the most up-to-date version of your app.
-
Edit & Refresh.
As you work, you continue to edit your original project files.
Do not modify the files in web/out because the compiler will overwrite them.
Embedding data in a web page with one-way data binding
The web app running below uses one-way data binding.
The Dart code computes the current time and
formats it into a String.
The HTML code embeds the value of that Dart String
into the HTML using the data binding feature provided by the Web UI package.
Use one-way data binding
when the value of the bound expression (here, a Dart string)
can change only in the Dart code.
You can find the complete source code for this sample on github at
littleben.
On the HTML side, the code uses a template expression
to embed the value of the String currentTime into the page.
In this example,
the expression is simply the name of a Dart variable
and it appears as part of an element’s text property.
A template expression is specified
with a double pair of curly brackets,
which enclose the expression to be evaluated:
{{expression}}.
Notice that it looks like a natural part of the HTML code.

On the Dart side,
the String currentTime is marked with @observable.
This marker causes the Web UI compiler to generate
the code needed to keep the HTML page in sync with this variable.
To use @observable,
the Dart code must import the Web UI package.
The value of currentTime changes every second
thanks to a periodic
Timer
object.
When the string changes,
the HTML page gets updated automatically.
This sample also uses the
DateTime
class to get the current time.
Binding the value of an element to a Dart variable
Using the Web UI package’s two-way data binding feature,
you can bind the value of an element,
typically an <input> element,
to the value of a Dart variable.
Try it! Type in the input field in the example running below.
You can find the complete source code for this sample on github at
shout.
The value of the text field is bound to a Dart string called shoutThis.
The string is declared
and marked with @observable
in the Dart code.
The string is bound to the input field in the HTML code
using the bind-value attribute.
As you type, the value of the string in the Dart program changes.
To demonstrate the change,
the UI displays variations of the string using several
one-way bound template expressions.
This is called two-way binding because the string can be changed
on the HTML-side when the user types,
or programmatically by the Dart code
(although you must be careful doing this.)

To bind data to the value of an element,
specify the bind-value attribute on an element in the HTML code.
For example, this is the code from the shout example that
binds the value of the text field to the shoutThis string:
<input type="text" bind-value="shoutThis" placeholder="Shout This!">
You can use bind-value with different kinds of input elements,
text areas, and select elements (drop-down lists.)
Also, you can use bind-checked with radio button elements and checkboxes.
And you can use bind-selected-index with select element.
About template expressions
A template expression can be any valid Dart expression
and is formed with double curly brackets: {{expression}}.
The expression is evaluated and converted to a string.
These are the template expressions used by the shout example:

| Expression |
Description |
| {{shoutThis.length}} |
Gets the length of the string. The returned value is an integer that gets converted to a string. |
| {{shoutThis.toUpperCase()}} |
Calls a string function that converts the string to upper case letters. Note that toUpperCase() returns a new string; it does NOT change the value of shoutThis. |
| {{(… ? … : … )}} |
Uses the conditional ternary operator; if the entered value is longer than 5 characters, a substring is displayed. |
| {{palindrome}} |
Calls a top-level function named palindrome(), defined in shout.dart, that creates a palindrome from the entered value. |

The palindrome function does NOT modify shoutThis.
If it did, it would create a situation in which an infinite loop is possible.
The Web UI system has a protection against infinite loops;
it detects if the values don’t converge
and stops the loop after several iterations.
However, this is simply a protection and not a feature you should rely on.
Use caution!
You should use expressions that are practically side-effect free.
Binding event handlers
The Web UI package provides a declarative way
to bind Dart event handlers to UI elements.
Each button in the stopwatch example below
has an event handler for responding to mouse clicks.
The event handlers are bound to the button in the HTML code
and implemented in Dart.
Try it! Click the buttons to start, stop, and reset the stop watch.
You can find the complete source code for this sample on github at
stopwatch.
Here’s the code that sets the mouse click handler for the Start button.

Event handlers are declared using attributes,
where the attribute name specifies the event type
using a hyphenated form of the Dart event name beginning with on-.
The buttons in the example specify event handlers for mouse clicks
using on-click.
Other common events
are double-click events (on-double-click)
and change events on input fields (on-change).
See the API docs for
Element
for a complete list of event names.
The attribute value is a Dart expression that usually
specifies a function call.
In the stopwatch example,
the startwatch() mouse click handler
is declared void and takes no arguments.
If the event handler needed information about the event that occurred,
it could accept an Event argument.
The event handler binding
in that case would be written on-click="startwatch($event)".
The function would be declared void startwatch(Event e).
Other resources