To write a Dart web app,
you need to have basic understanding of
several topics—the DOM tree, nodes, elements,
HTML, Dart language and libraries,
and Dart Editor.
The interdependencies are circular,
but we have to begin somewhere,
so we begin with a simple HTML file,
which introduces the DOM tree and nodes.
From there,
you build a bare bones, stripped-down
Dart application
that contains just enough code to
dynamically put text on the page from the Dart side.
Though simple,
this example shows you how to connect a Dart
app to an HTML page and
one way that a Dart app can interact with items on the page.
These concepts
provide the foundation
for more interesting and useful web apps.
About the DOM
The Document Object Model (DOM)
represents the structure of a web document as a tree of nodes.
When an HTML file is loaded into a browser,
the browser interprets the HTML
and displays the document in a window.
The following diagram shows a simple HTML file and
the resulting web browser page in Chrome.

HTML uses tags to describe the document.
For example, the simple HTML code above
uses the <title> tag for the page title,
<h1> for a level-one header,
and <p> for a paragraph.
Some tags in the HTML code,
such as
<head> and <body>,
are not visible on the web page,
but do contribute to the structure of the document.
In the DOM,
the document object sits at the root of the tree
(it has no parent).
Different kinds of nodes in the tree
represent different kinds of objects in the document.
For example, the tree has page elements,
text nodes, and attribute nodes.
Here is the DOM tree for the simple HTML file above.

Notice that some tags, such as the <p> paragraph tag,
are represented by multiple nodes.
The paragraph itself is an element node.
The text within the paragraph is a text node
(and in some cases, might be a subtree containing many nodes).
And the ID is an attribute node.
Except for the root node, each node in the tree has exactly one parent.
Each node can have many children.
An HTML file defines the initial structure of a document.
Dart or JavaScript can dynamically modify that document
by adding, deleting, and modifying the nodes in the DOM tree.
When the DOM is changed,
the browser immediately re-renders the window.

The diagram shows a small Dart program that makes
a modest change to the DOM by dynamically
changing a paragraph’s text.
A program could add and delete nodes,
or even insert an entire sub-tree of nodes.
Create a new Dart app
The application you write in this target will be a web application.
Web applications use code from the browser package to run inside of a browser,
so you need to start with the supporting files and packages
even for the smallest web app.
In Dart Editor, create a new application called mini.
Select Generate sample content
and Web application.

Dart Editor creates a directory called mini and, within it,
the files and directories needed for a web application.

-
The top-level directory is named after the application.
-
The pubspec.yaml file is used by applications
that rely on external packages of Dart code.
Target 5: Install Shared Packages
provides more information.
Web applications use a package called browser.
This dependency is declared in the pubspec.yaml file.
-
The web directory contains the Dart, HTML, and CSS code for the web app.
-
The main source file, mini.dart in this sample,
contains boilerplate code for the clickme app
you saw in the previous target.
You will edit the code in this file and
in mini.html to create a bare-bones app.
Edit Dart source code
Use Dart Editor
to modify the source code
to look like this:
import 'dart:html';
void main() {
query('#RipVanWinkle').text = 'Wake up, sleepy head!';
}
What is Dart Editor trying to tell me?
About the Dart source code
Let’s step through the code.
Importing libraries
The import directive imports the specified library,
making all of the classes and functions
in that library
available to your program.

This program imports Dart’s HTML library,
which contains the classes and functions for programming the DOM.
Generally speaking, all Dart web apps need the Dart HTML library.
Key classes include:
| Dart class |
Description |
| Node |
Implements a Dart Node. |
| Element |
A subclass of Node, implements a web page element. |
| Document |
Another subclass of Node. Implements the document object. |
The Dart core library contains another useful class,
List,
a parameterized class that can specify the type of its members.
The Element class keeps its list of child Elements
in a List<Element>, a list that can contain only Element objects.
Using the query() function
This app’s main() function contains a single
line of code that is a little like a run-on sentence
with multiple things happening one after another.
Let’s deconstruct it.
query() is a top-level function provided by the Dart HTML library
that gets an Element object from the DOM.

The argument to query(), a string,
is a CSS selector that identifies the object.
Most commonly CSS selectors specify classes, identifiers, or attributes.
We’ll look at these in a little more detail later,
when we add a CSS file to the mini app.
In this case RipVanWinkle is the unique ID for a paragraph element
declared in the HTML file
and #RipVanWinkle specifies that ID.

Another useful function for getting elements from the DOM
is queryAll(),
which returns multiple Element objects via
a list of elements—List—all
of which match the provided selector.
Setting the text of an Element
In the DOM, the text of a page element is contained
in a child node, specifically, a Text node.
In the following diagram,
the node containing the string
“RipVanWinkle paragraph.”
is a text node.

More complex text,
such as text with style changes or
embedded links and images,
would be represented with a subtree of text nodes and other objects.
In Dart,
you can simply use the Element text property,
which has a getter
that walks the subtree of nodes for you and extracts their text.

However, if the text node has styles (and thus a subtree),
getting text and then setting it immediately is likely
to change the DOM, as a result of losing subtree information.
Often, as with our RipVanWinkle example,
this simplification has no adverse effects.
Do know, however, that with more complex situations
getting text and then setting it immediately
will likely change the text.
The assignment operator (=) sets the text
of the Element returned by the query() function
to the string “Wake up, sleepy head!”.

This causes the browser to immediately re-render
the browser page containing this app
dynamically displaying the text on the browser page.
Edit the HTML file
When Dart Editor created the application,
it created boilerplate HTML code that worked with the clickme app.
Now that you’ve modified the Dart code,
you will need to change the HTML code
so that it contains the expected RipVanWinkle paragraph.
In Dart Editor, double click mini.html.
The code appears in the editor pane.
Replace the default contents with the following,
simplified HTML.
<!DOCTYPE html>
<html>
<head>
<title>A Minimalist App</title>
</head>
<body>
<p id="RipVanWinkle"></p>
<script type="application/dart" src="mini.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
Finish your edits and save the file with File > Save.
About the HTML source code
This HTML code is similar to the simple HTML code in the
various diagrams earlier in this target.
Again, you can see the use of the <head>, <title>, <body>,
and <p> tags.
And there, in the paragraph tag,
is the identifier “RipVanWinkle”
that the Dart code you created in the previous step uses
as an argument to query() to get the paragraph element.
New here is the use of the script tag.
A script’s content is defined by a client-side script.
The HTML code above has two scripts.

The first includes your mini app.
It uses two attributes: type indicates the type of the script.
application/dart is a new type created by the Dart team,
which is currently supported by Dartium.
The src attribute provides the URL to the source file of the script.
In this case, it is the Dart source file mini.dart that you created earlier.
The Dart file should be in the same directory as its host HTML file.
The second script tag is
a bootstrap script that takes care of turning on the Dart VM,
as well as compatibility with non-Dart browsers.
This diagram summarizes the connection
between mini.dart and mini.html.

Run the mini web app
In Dart Editor,
make sure that one of mini’s files or the directory is selected,
and then click the Run button
.
Dart Editor invokes Dartium
and loads mini.html in it.
Below is mini app running in a frame.
The app just displays a line of text.
The Dart web app changed
the text in the browser window dynamically at runtime.
Of course, placing static text on a browser page
and doing nothing else
could be accomplished with straight HTML.
This little app only shows you how to make a connection
from a Dart app to a browser page.
Create a JavaScript launch
You can create various runtime scenarios for your Dart app
using launches in Dart Editor.
A launch specifies a runtime configuration,
such as whether to compile to JavaScript
or what browser to use.
In this section,
you will create a launch for mini that first compiles the app to
JavaScript and then runs it in the default system browser.
-
In Dart Editor,
click the wee arrow to the right of the run button
.
A menu appears:

You have been unwittingly using launches when running
the samples so far.
The menu item mini.html from mini is a launch that Dart Editor
automatically created
when you ran the application for the first time
in the previous section.
-
Select Manage launches from the menu
to bring up the Manage Launches dialog.
Using the small icons,
you can create launches for different purposes:

By default,
Dart Editor automatically creates a Dartium launch for web apps.
You must explicitly create a Dart JavaScript launch
to create a runtime configuration that compiles
your web app to JavaScript and then runs it in a browser.
-
Click the JavaScript launch icon
.
The dialog window adjusts to present the appropriate options
for your selection.
-
Name the launch by typing mini-with-js in the first text box.

It is recommended that the launch name reflect
the important aspects of its configuration.
In this case, the launch name specifies the app name
and that it’s a JavaScript launch.
If the launch specified a browser, such as FireFox,
you might name the launch mini-with-js-in-firefox.
-
The launch target is the HTML file mini.html.
Browse to the file.
-
Click Apply.
The named launch should now appear
in the list to the left of the window.

-
To run the launch,
click the Run button at the bottom right of the window.
Or select it from the Run menu on the main Dart Editor window.
This time, Dart Editor
creates a JavaScript file,
invokes the default system browser
and loads the JavaScript file into it.
The output should look the same.
Give the app some style with CSS
Most HTML uses cascading style sheets (CSS) to define styles
that control the appearance of page elements.
Let’s customize the CSS for the mini app.
In Dart Editor, edit the file named mini.css
and replace the contents of the file with
the following CSS code:
#RipVanWinkle {
font-size: 20px;
font-family: 'Open Sans', sans-serif;
text-align: center;
margin-top: 20px;
background-color: SlateBlue;
color: Yellow;
}
This defines a style
for the page element
with the ID RipVanWinkle.
To use this style sheet,
edit mini.html and add the line shown in bold below:

Save your files and run the app again.
Below is the revised mini app,
which is slightly more colorful
but still neither interactive nor interesting.
About CSS selectors
IDs, classes, and other information about elements
are established in HTML.
Your Dart code can use this information
to get elements using a CSS selector—a pattern
used to select matching elements in the DOM.
CSS selectors allow the CSS, HTML, and Dart code
to refer to the same objects.
Commonly, a selector specifies an ID,
an HTML element type,
a class, or an attribute.
Selectors can also be nested.
CSS selectors are important in Dart programs
because you use them with query() and queryAll()
to get matching elements from the DOM.
Most often Dart programs use ID selectors with query()
and class selectors with queryAll().
Here are some examples of CSS selectors:
| Selector type |
Example |
Description |
| ID selector |
#RipVanWinkle |
Matches a single, unique element |
| HTML element |
p |
Matches all paragraphs |
| HTML element |
h1 |
Matches all level-one headers |
| Class |
.classname |
Matches all items with the class classname |
| Asterisk |
* |
Using the asterisk matches all elements |
| Attribute |
input[type=”button”] |
Matches all button input elements |
Let’s look at the CSS code for mini app.
The CSS file for the mini app has one CSS rule in it.
A CSS rule has two main parts: a selector and a set of declarations.

In mini app, the selector #RipVanWinkle is an ID selector,
as signaled by the hash tag (#);
it matches a single, unique element with the specified ID,
our now tired RipVanWinkle paragraph element.
RipVanWinkle is the ID in the HTML file.
It is referred to in the CSS file and in the Dart code
using a hash tag(#).
Classnames are specified in the HTML file without a period (.)
and referred to in the CSS file and in Dart code with a period (.).
Between the curly brackets of a CSS rule is
a list of declarations,
each of which ends in a semi-colon (;).
Each declaration specifies a property and its value.
Together the set of declarations define the style sheet
for all matching elements.
The style sheet is used to set the appearance
of the matching element(s) on the web page.

The CSS rule for the RipVanWinkle paragraph
specifies several properties;
for example, it sets the text color to Yellow.
Other resources
-
Dart Up and Running
provides thorough coverage of the Dart language, libraries, and tools.
If a topic is not covered explicitly here,
you can find the information you need there.
-
Dart Editor,
an excerpt from Dart Up and Running,
provides details about using Dart Editor.
The excerpt includes, for example,
how to use Dart Editor's power features such as autocompletion and refactoring,
how to set up different run-time environments, and so on.
-
Also, check out
Dart Cookbook,
where you'll find many recipes about
manipulating the DOM and using CSS.
The cookbook also has recipes about basic Dart data types,
such strings, lists, maps, and numbers.