Connect Dart & HTML

This tutorial is the first of a series on basic, low-level web programming with the dart:html library. If you use a web framework like AngularDart, some of these concepts might be useful, but you might not need to use the dart:html library at all.

What’s the point?

  • DartPad lets you write a simple Dart web app without HTML boilerplate.
  • A Dart web app has Dart, HTML, and (usually) CSS code.
  • Compile a web app’s Dart code to JavaScript to run the app in any modern browser.
  • An HTML file hosts your Dart code in a browser page.
  • The DOM models a browser page in a tree/node structure.
  • Use querySelector() with an ID to get an element from the DOM.
  • CSS selectors are patterns used to select matching elements in the DOM.
  • Use CSS rules to style elements.

To write a low-level web app with Dart, you need to understand several topics—the DOM tree, nodes, elements, HTML, and the Dart language and libraries.

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 app 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 Dart, HTML, and CSS triumvirate

If you’ve used DartPad, you’ve already seen the DART, HTML, and CSS tabs that let you write the code for a web app. Each of these three languages is responsible for a different aspect of the web app.

LanguagePurpose
DartImplements the interactivity and dynamic behavior of the web app
HTMLDescribes the content of the web app’s page (the elements in the document and the structure)
CSSGoverns the appearance of page elements

A Dart program can respond to events such as mouse clicks, manipulate the elements on a web page dynamically, and save information. Before the web app is deployed, the Dart code must be compiled into JavaScript code.

HTML is a language for describing web pages. Using tags, HTML sets up the initial page structure, puts elements on the page, and embeds any scripts for page interactivity. HTML sets up the initial document tree and specifies element types, classes, and IDs, which allow HTML, CSS, and Dart programs to refer to the same elements.

CSS, which stands for Cascading Style Sheets, describes the appearance of the elements within a document. CSS controls many aspects of formatting: type face, font size, color, background color, borders, margins, and alignment, to name a few.

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.

A simple HTML file and its resulting web page

HTML uses tags to describe the document. For example, the simple HTML code above uses the 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.</p> <p>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.</p> <p><img src="/projects/dart-2.8-en/d43048c5462157fee4b054ade08d98c5.png" alt="The DOM tree for a simple HTML file"></p> <p>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.</p> <p>Except for the root node, each node in the tree has exactly one parent. Each node can have many children.</p> <p>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.</p> <p><img src="/projects/dart-2.8-en/33c3283b8a9ab26dc86a4f9d734750d5.png" alt="A Dart program can dynamically change the DOM"></p> <p>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 subtree of nodes.</p> <h2 id="7ssxh"><a name="7ssxh" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Create a new Dart app</h2><ol> <li>Go to <a href="https://dartpad.dev">DartPad.</a></li><li>Click the <strong>New Pad</strong> button to undo any changes you might have made the last time you visited DartPad.</li><li>Select the <strong>Show web content</strong> checkbox at the bottom right corner, so you can edit HTML and CSS in DartPad.</li></ol> <p><strong>Note:</strong> These instructions feature DartPad, which hides some of the HTML boilerplate code. If you want to use any other editor, then we recommend starting with a small Dart web app sample and modifying the non-script tags inside the <body> section. <a href="#connections">HTML and Dart connections</a> shows the full HTML code.</p> <h2 id="eu15my"><a name="eu15my" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Edit the HTML source code</h2><ol> <li><p>Click <strong>HTML</strong>, at the upper left of DartPad. The view switches from Dart code to the (non-existent) HTML code.</p> </li><li><p>Add the following HTML code:</p> <pre><code><p id="RipVanWinkle"> RipVanWinkle paragraph. </p> </code></pre></li><li><p>Click <strong>HTML OUTPUT</strong> to see how a browser would render your HTML.</p> </li></ol> <h2 id="3kiz8f"><a name="3kiz8f" class="reference-link"></a><span class="header-link octicon octicon-link"></span>About the HTML source code</h2><p>This HTML code is similar to the HTML code in the various diagrams earlier in this tutorial, but it’s even simpler.</p> <p>In DartPad you need only the tags you really care about—in this case, <p>. You don’t need surrounding tags such as <html> and <body>. Because DartPad knows where your Dart code is, you don’t need a <script> tag.</p> <p><strong>Note:</strong> <a href="#connections">HTML and Dart connections</a> shows the full HTML code that you need to run your web app outside of DartPad.</p> <p>The paragraph tag has the identifier “RipVanWinkle”. The Dart code you create in the next step uses this ID to get the paragraph element.</p> <h2 id="g1a6j0"><a name="g1a6j0" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Edit the Dart source code</h2><ol> <li><p>Click <strong>DART</strong>, at the upper right of DartPad. The view switches from HTML code to Dart code.</p> </li><li><p>Change the Dart code to the following:</p> <pre><code>import 'dart:html'; void main() { querySelector('#RipVanWinkle').text = 'Wake up, sleepy head!'; } </code></pre></li><li><p>Click <strong>Run</strong> to execute your code.</p> </li></ol> <p>The text in the HTML OUTPUT tab changes to “Wake up, sleepy head!”</p> <h2 id="9pe4u7"><a name="9pe4u7" class="reference-link"></a><span class="header-link octicon octicon-link"></span>About the Dart source code</h2><p>Let’s step through the Dart code.</p> <h3 id="4ufsza"><a name="4ufsza" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Importing libraries</h3><p>The import directive imports the specified library, making all of the classes and functions in that library available to your program.</p> <pre><a href="#" class="dart-popover" data-toggle="popover" data-html="true" data-trigger="hover focus" data-content="Imports Dart's HTML classes and functions">import 'dart:html';</a> </pre> <p>This program imports Dart’s HTML library, which contains key classes and functions for programming the DOM. Key classes include:</p> <table><thead><tr><th>Dart class</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://api.dart.dev/stable/dart-html/Node-class.html" target="_blank" rel="noopener">Node</a></td><td>Implements a DOM node.</td></tr><tr><td><a href="https://api.dart.dev/stable/dart-html/Element-class.html" target="_blank" rel="noopener">Element</a></td><td>A subclass of Node; implements a web page element.</td></tr><tr><td><a href="https://api.dart.dev/stable/dart-html/Document-class.html" target="_blank" rel="noopener">Document</a></td><td>Another subclass of Node; implements the document object.</td></tr></tbody></table> <p>The Dart core library contains another useful class: <a href="https://api.dart.dev/stable/dart-core/List-class.html">List,</a> a parameterized class that can specify the type of its members. An instance of Element keeps its list of child Elements in a List<Element>.</p> <h3 id="4ilz4p"><a name="4ilz4p" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Using the querySelector() function</h3><p>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.</p> <p>querySelector() is a top-level function provided by the Dart HTML library that gets an Element object from the DOM.</p> <pre><a href="#" class="dart-popover" data-toggle="popover" data-html="true" data-trigger="hover focus" data-content="Returns the matching Element">querySelector('#RipVanWinkle')</a>.text = 'Wake up, sleepy head!'; </pre> <p>The argument to querySelector(), 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 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.</p> <pre>querySelector(<a href="#" class="dart-popover" data-toggle="popover" data-html="true" data-trigger="hover focus" data-content="ID from HTML file">'#RipVanWinkle'</a>).text = 'Wake up, sleepy head!'; </pre> <p>Another useful function for getting elements from the DOM is querySelectorAll(), which returns multiple Element objects via a list of elements—List—all of which match the provided selector.</p> <h3 id="dcgw4y"><a name="dcgw4y" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Setting the text of an Element</h3><p>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.</p> <p><img src="/projects/dart-2.8-en/44aed74da965123311b86731db62a403.png" alt="DOM tree for a paragraph element"></p> <p>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.</p> <p>In Dart, you can simply use the Element <code>text</code> property, which has a getter that walks the subtree of nodes for you and extracts their text.</p> <pre>querySelector('#RipVanWinkle')<a href="#" class="dart-popover" data-toggle="popover" data-html="true" data-trigger="hover focus" data-content="Convenience API to the Element's text">.text</a> = 'Wake up, sleepy head!'; </pre> <p>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.</p> <p>The assignment operator (=) sets the text of the Element returned by the querySelector() function to the string “Wake up, sleepy head!”.</p> <pre>querySelector('#RipVanWinkle').text <a href="#" class="dart-popover" data-toggle="popover" data-html="true" data-trigger="hover focus" data-content="Dynamically changes the DOM">=</a> 'Wake up, sleepy head!'; </pre> <p>This causes the browser to immediately re-render the browser page containing this app, thus dynamically displaying the text on the browser page.</p> <h2 id="34ya1f"><a name="34ya1f" class="reference-link"></a><span class="header-link octicon octicon-link"></span>HTML and Dart connections</h2><p>The Dart web app changed the text in the browser window dynamically at runtime. Of course, placing 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.</p> <p>In DartPad, the only visible connection between the Dart code and the HTML code is the RipVanWinkle ID.</p> <p><img src="/projects/dart-2.8-en/ef4aebcb691a486b64e62624b5d725b4.png" alt="The RipVanWinkle ID is used by both Dart and HTML"></p> <p>To run your app outside of DartPad, you need to compile your Dart code to JavaScript. <a href="$c07db65fb3b6645e.md#build">Use the <strong>webdev build</strong> command</a> to compile your app to deployable JavaScript. Then you need to make another connection between the HTML and generated JavaScript: you must add a <script> tag to the HTML to tell the browser where to find the compiled Dart code.</p> <p>Here’s the full HTML code for this app, assuming that the Dart code is in a file named <code>main.dart</code>:</p> <pre><code><!DOCTYPE html> <html> <head> <title>A Minimalist App</title> <script defer src="main.dart.js"></script> </head> <body> <p id="RipVanWinkle"> RipVanWinkle paragraph. </p> </body> </html> </code></pre><p>The <code><script></code> element specifies the location of the compiled Dart code.</p> <h2 id="1hxj9n"><a name="1hxj9n" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Give the app some style with CSS</h2><p>Most HTML uses cascading style sheets (CSS) to define <em>styles</em> that control the appearance of page elements. Let’s customize the CSS for the mini app.</p> <ol> <li><p>Click <strong>CSS</strong>. The view switches from Dart code to the (non-existent) CSS code.</p> </li><li><p>Add the following CSS code:</p> <pre><code>#RipVanWinkle { font-size: 20px; font-family: 'Open Sans', sans-serif; text-align: center; margin-top: 20px; background-color: SlateBlue; color: Yellow; } </code></pre></li></ol> <p>The display under HTML OUTPUT immediately changes to reflect the new styles, which apply only to the page element that has the ID RipVanWinkle.</p> <h2 id="cwcxou"><a name="cwcxou" class="reference-link"></a><span class="header-link octicon octicon-link"></span>About CSS selectors</h2><p>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.</p> <p>CSS selectors are important in Dart programs because you use them with querySelector() and querySelectorAll() to get matching elements from the DOM. Most often Dart programs use ID selectors with querySelector() and class selectors with querySelectorAll().</p> <p>Here are some examples of CSS selectors:</p> <table><thead><tr><th>Selector type</th><th>Example</th><th>Description</th></tr></thead><tbody><tr><td>ID selector</td><td>#RipVanWinkle</td><td>Matches a single, unique element</td></tr><tr><td>HTML element</td><td>p</td><td>Matches all paragraphs</td></tr><tr><td>HTML element</td><td>h1</td><td>Matches all level-one headers</td></tr><tr><td>Class</td><td><em>.classname</em></td><td>Matches all items with the class <em>classname</em></td></tr><tr><td>Asterisk</td><td>*</td><td>Matches all elements</td></tr><tr><td>Attribute</td><td>input[type=”button”]</td><td>Matches all button input elements</td></tr></tbody></table> <p><strong>Tip:</strong> As you saw, the mini app used a CSS selector, the ID #RipVanWinkle, even when there was no CSS file. You do not need a CSS file for a Dart program. Nor do you need a CSS file to use CSS selectors. CSS selectors are established in the HTML file and used by the Dart program to select matching elements.</p> <p>Let’s look at the CSS code for the 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.</p> <p><img src="/projects/dart-2.8-en/f3210fdd9855d13494ac8a4f81151823.png" alt="The parts of a CSS rule"></p> <p>In the 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 (.).</p> <p>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 <em>style sheet</em> for all matching elements. The style sheet is used to set the appearance of the matching element(s) on the web page.</p> <p><img src="/projects/dart-2.8-en/8cf953e28e0f197523d65307f062dea6.png" alt="A declaration specifies an attribute and its value"></p> <p>The CSS rule for the RipVanWinkle paragraph specifies several properties; for example, it sets the text color to Yellow.</p> <h2 id="95cxyi"><a name="95cxyi" class="reference-link"></a><span class="header-link octicon octicon-link"></span>Other resources</h2><ul> <li>The <a href="$71a230398ab31385.md">language tour</a> provides thorough coverage of the Dart language.</li><li><a href="$1db7a7d2b0daba81.md">Dart tools page</a> lists IDEs and editors that have Dart plugins.</li></ul> <h2 id="a5jmt3"><a name="a5jmt3" class="reference-link"></a><span class="header-link octicon octicon-link"></span>What next?</h2><p>The next tutorial, <a href="$d3c08fd54fa331df.md">Add elements to the DOM</a>, shows you how to dynamically change the HTML page by adding elements to the DOM.</p> <ul> <li><a href="$d3c08fd54fa331df.md">Add elements to the DOM ⟩</a></li></ul> <!-- 原文:https://dart.dev/tutorials/web/low-level-html/connect-dart-html -->