Learning Dart - Second Edition

4 (3 reviews total)
By Ivo Balbaert , Dzenan Ridjanovic
    What do you get with a Packt Subscription?

  • Instant access to this title and 7,500+ eBooks & Videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Free Chapter
    Dart – A Modern Web Programming Language

About this book

Dart is an open source programming language for the web, developed at Google, with a steadily growing community. It is a single language for both client and server, appropriate for the full range of devices on the web – including phones, tablets, laptops, and servers. It encompasses the lessons of the last two decades of web programming.

This book will give you a thorough overview of Dart, taking you through its ecosystem, syntax, and development principles.

With this book, you will build web games using HTML5, audio, and video, and also dive into processing and displaying data in HTML5 forms with Dart. You will also learn how web components fit together with HTML5, and how to apply them in business web applications of the future. You will discover how to store data on the client, communicate data between client and server with JSON, and store JSON data with MongoDB and MySQL.

Stop solving new challenges with the same old tools – let Dart show you a whole new way.

Publication date:
September 2015
Publisher
Packt
Pages
382
ISBN
9781785287626

 

Chapter 1. Dart – A Modern Web Programming Language

In this chapter, we will investigate:

  • What Dart is all about

  • Why it is a major step forward in the web programming language arena

  • Getting started with Dart programming

We will get started with the Dart platform and have a look at its tools. Before this, we will be programming and taking a dive into a simple functional to-do list program so that you realize how familiar it all is.

 

What is Dart?


Dart is a new general and open source programming language with a vibrant community developed by Google Inc. and its official website is http://www.dartlang.org. It was first announced as a public preview on October 10, 2011; it has now reached version 1.10. World class language designers and developers are involved in this project, namely, Lars Bak and Kasper Lund (known for their V8 JavaScript engine embedded in the Chrome browser, which revolutionized performance in the JavaScript world), and Gilad Bracha (a language theorist known for the development of the Strongtalk and Newspeak languages and for the Java specification). Judging by the huge amount of resources and the number of teams working on it, it is clear that Google is very serious about making Dart a success.

Tip

Take your time to familiarize yourself with the https://www.dartlang.org/ site. It contains a wealth of information, code examples, presentations, and so on to supplement this book, and we will often reference it.

Dart looks instantly familiar to the majority of today's programmers coming from a Java, C#, or JavaScript (JS) (ActionScript) background; you will feel at ease with Dart. However, this does not mean that it is only a copy of what already exists; it takes the best features of the statically typed "Java-C#" world and combines these with features more commonly found in dynamic languages such as JS, Python, and Ruby. On the nimble, dynamic side Dart allows rapid prototyping, evolving into a more structured development familiar to business app developers when application requirements become more complex.

Its main emphasis lies on building complex (if necessary), high performance, and scalable-rich client apps for the modern web. By modern web, we mean that it can execute in any browser on any kind of (client) device, including tablets and smartphones, taking advantage of all the features of HTML5, and it is ported to the ARM-architecture and the Android platform. Dart is designed with performance in mind by the people who developed V8. Because the Dart team at Google believes web components will be the foundation for the next evolution of web development, there is strong Dart support for the Polymer framework (web components are pieces of the web code containing HTML and Dart or JavaScript that you can reuse in different pages and projects. In other words, it is a reliable infrastructure of widgets). However, Dart can also run independently on servers. Because Dart clients and servers can communicate through web sockets (a persistent connection that allows both parties to start sending data at any time), it is, in fact, an end-to-end solution. It is perfect on the frontend to develop web components with all the necessary application logic, nicely integrated with HTML5 and the browser document model (DOM). On the backend server side, it can be used to develop web services, for example, to access databases, or cloud solutions in Google App Engine or other cloud infrastructures.

Moreover, it is ready to be used in the multicore world (remember, even your cell phone is multicore nowadays), because a Dart program can divide its work among any number of separate processes called isolates, an actor-based concurrency model as in Erlang.

 

Dart is a perfect fit for HTML5


To appreciate this fully, we have to take a look at the history of client-side web development.

A very short history of web programming

A web application is always a dialog between a client-browser requesting a page and the server responding with processing and delivering the page and its resources (such as pictures and other media). In the technology of the early dynamic web (the 90s of the previous century, extending even until today), the server performed most of the work: compiling a page, executing the code, fetching data from a data store, inserting the data in the page templates, and in the end, producing a stream of HTML and JavaScript, which was delivered to the browser. The client digested this stream, rendering the HTML into a browser screen while executing some JavaScript, so processing on the client side was minimal. The whole range of applications using Perl, Python, Ruby, PHP, JSP (Java Server Pages), and ASP.NET follows this principle. It is obvious that the heavy server loads impact negatively the number of clients that could be served as well as the response time in these applications. This mismatch is even clearer when we realize that the power of the client platforms (with their multicore processors and large memories) is heavily underutilized in this model.

The plugin model, within which the browser started specialized software (such as the Adobe Flash Player) to handle all kinds of media and other resources, partly tipped the balance to the client side. Following this trend, a whole range of technologies for developing Rich Internet applications (RIA) were developed that executed application code in the browser at the client side instead, ranging from Java applets around 1995 to Microsoft Active X Objects, culminating in the Adobe Flex and Microsoft Silverlight frameworks. While they have their merits, it is clear that they are more like a parasite in the browser; a virtual machine that executes, for example, ActionScript or C# code that is alien to the browser environment.

Dart empowers the web client

Empowering the client is the way to go, but this should better be done with software technology intimately linked to the browser itself: HTML and JavaScript. In order to eliminate the need for alien plugins, the power of HTML needs to be enlarged. This is precisely what is achieved with HTML5, for example, with its <audio> and <video> tags. JavaScript is the ubiquitous language of the web and it can, like Dart, request/send data from/to the server without blocking the user experience through technologies such as Ajax. However, flexible and dynamic as JavaScript may be, today it is also often called the assembly language for the web.

JavaScript is not the way to go

Why is this? JavaScript was, from the beginning, not designed to be a robust programming language, despite its name that suggests an affiliation with Java. It was designed to be a simple interpreted language, which could be used by nonprofessional programmers and that would be complemented by Java for more serious work. However, Java went away to prosper on the server and JavaScript invaded the browser space. Today, JS is being used to develop big and complex web applications, with server components such as Node.js, far beyond the original purpose of this language. Most people who have worked on a large client-side web application written entirely in JS will sooner or later come to the conclusion that its use in these applications is overstretched and the language was not meant to build this kind of software.

Understanding program structure is crucial in large, complex applications: this makes code maintenance, navigating in code, debugging, and refactoring easier. Unfortunately, JS code is hard to reason about, because there is almost no declarative syntax and it is very hard to detect dependencies between different scripts that can appear in one web page. JavaScript is also very permissive: almost anything (spelling mistakes, wrong types, and so on) is tolerated, making it hard to find errors and unpredictable results. Furthermore, JS allows you to change the way built-in core objects function, a practice often called monkey patching (for a reason!). Would you trust a language in which the following statement is true in its entirety and all of its comparisons?

10.0 == '10' == new Boolean(true) == '1'

Because of this sometimes undefined nature of JS, its performance is often very unpredictable, so building high performance web apps in it is tricky.

Google, GWT, and Dart

Google is the web firm par excellence: its revenue model is entirely based on its massive web applications, such as Gmail (some half a million lines of JS), Google Docs, Google Maps, and Google Search. So, it is no wonder that these teams encountered the difficulties of building a large JS application and strived for a better platform. Due to the fundamental flaws of JS and its slow evolution, something better was needed. A first attempt was Google Web Toolkit (GWT), where the development was done in Java, which was then compiled to JS. Although it was reasonably successful because it enabled a structured and tooled approach to application building, it was clear that the use of Java is somewhat awkward in a web environment. Thus, arose the idea for Dart: a kind of hybrid platform between the dynamic nature of JS and the structured and toolable languages such as Java and C#. In order for Dart to run in all modern web browsers like GWT, it must be compiled to JS. Google has provided a special build of Chromium, called Dartium, which provides a Dart VM to execute Dart code on the fly without any compilation step. This is useful for testing in Dart Editor (Chrome or any other browser can be used to test the JS version of your Dart app).

Advantages of Dart

This way, Dart can get a better performance profile than JS (remember that the same experts who developed the V8 JS VM are forging Dart, see http://www.dartlang.org/performance/) and, at the same time, maintain the simple and rapid development process of JS in the browser: the edit code, save, and refresh browser cycle to view the latest version, rather than having to stop, recompile, and run for every little change. Dart delivers high performance on all the modern web browsers and environments ranging from small handheld devices to server-side execution. When it runs on its own VM, Dart is faster than JS (currently, around 1.5 times the performance of JS). Moreover, through snapshotting (a mechanism inherited from Smalltalk), a Dart app has a fast application startup time in contrast to JS, where all the source code has to be interpreted or compiled from the source.

Dart executes in the browser after having been compiled to JS, so Dart runs everywhere JS does. The Dart VM can also run standalone on a client or server.

Another big advantage compared with GWT is that Dart is much better integrated with the web page and like JS can directly manipulate the page elements and the document structure, that is, the Document Object Model (DOM). Like JS, it has intimate access to the new HTML5 APIs, for example, drawing with the canvas, playing audio and video clips, or using the new local storage possibilities. Following the RIA model explained earlier, Dart executes the full application code in the browser, requesting data from the server and rebuilding the page user interface when needed. Because Dart wants to be a part of the web, not just sit on the top, the team has also built a Dart to JavaScript interop layer to call JavaScript from Dart and the other way around. Together with its out-of-browser and server capabilities, Dart is also conceived to build complex, large-scale web applications. This can be clearly seen from its object-oriented nature, and Dart code is built with code clarity and structure (using libraries and packages) in mind. To summarize it:

  • Dart compiles to JavaScript

  • Dart is faster than JavaScript while running in its VM (as a server standalone application, or in Dartium, which is a special build of the Chromium browser)

  • Dart is better suited for large scale applications

    The Dart web model

 

Getting started with Dart


The Dart project team wants us to get an optimal development experience, so they provide a full but lightweight IDE: the Dart Editor, a light version of the well-known Eclipse environment. Installing this is the easiest way to get started, because it comprises the full Dart environment. Another awesome editor is WebStorm from JetBrains (see https://www.dartlang.org/tools/webstorm/).

Installing the Dart Editor

Because Eclipse is written in Java, we need a Java Runtime Environment (JRE), version 6 or higher, on our system (this is not needed for Dart itself, only for the Dart Editor). To check whether this is already the case, go to http://www.java.com/en/download/installed.jsp.

If it is not the case, head to http://www.oracle.com/technetwork/java/javase/downloads/index.html, click on the JRE DOWNLOAD button, choose the JRE for your platform, and then click on Run to start the installation.

Then, go to http://www.dartlang.org/ and click on the GET STARTED and Download Dart menu item. Under Download the SDK, choose the appropriate button (according to whether your installed OS is 32-bit or 64-bit) to download the editor.

Tip

This is also the page where you can download the SDK separately, or the Dartium browser (a version of Chromium to test your Dart apps) or download the Dart source code.

You are prompted to save a file named darteditor-os-nn.zip, where OS can be Windows, Linux, or MacOS, and nn is 32 or 64. Extracting the content of this file will create a folder named dart containing everything you need: dart-sdk, dartium, and DartEditor. This procedure should go smoothly, but if you encounter a problem, please review http://www.dartlang.org/docs/editor/getting-started/.

Note

In case you get the following error message: Failed to load the JNI shared library C:\Program Files(x86)\Java\jre6\bin\client\jvm.dll, do not worry. This happens when JRE and Dart Editor do not have the same bit width. More precisely, this happens when you go to http://www.java.com/ to download JRE. In order to be sure what JRE to select, it is safer to go to http://www.oracle.com/technetwork/java/javase/downloads/index.html, click on the JRE DOWNLOAD button, and choose the appropriate version. If possible, use a 64-bit versions of JRE and Dart Editor. There could be another problem related to JRE. After unzipping a Dart Editor file, it is recommended to copy the jre folder from the Java folder to the dart folder (where the DartEditor.exe file is located). Again, it is important to copy the correct bit width version. If the 64-bit version of Dart Editor is used, the 64-bit version of JRE must be copied. This version is in the Program Files/Java folder under the jre7 name (don't copy the jre7 folder from Program Files (x86) / Java, this is the 32-bit version). Finally, after the jre7 folder is copied, it must be renamed from jre7 to jre.

Other options for working with Dart code

If you are more familiar working in the Eclipse environment, you can simply use the Dart Eclipse plugin (https://www.dartlang.org/tools/eclipse-plugin/), which provides the same functionality as Dart Editor. Another rich working environment alternative is built in the WebStorm environment from IntelliJ: https://www.dartlang.org/tools/webstorm/.

If you need a cloud environment, you can use DartPad for simpler projects: https://dartpad.dartlang.org/.

Your first Dart program

Double-click on DartEditor.exe to open the editor. Navigate to File | New Project or click on the first button below the menu (Create a new Dart Project...). Fill in an application name (for example, dart1) and choose the folder you want the code file to be created (make a folder such as dart_apps to provide some structure; you can do this while using the Browse button). We will leave the Console application – A simple command-line application selection.

With these names, a dart1 folder is made as a subfolder of dart_apps and a main.dart source file is created in dart1\bin with the following code (we'll explain pubspec.yaml and the packages folder in one of the following examples). For now, replace its contents with the following code:

void main() {
  print("Hello, World!");
}

Tip

Downloading the example code

You can download the example code files for all the Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Here, we see immediately that Dart is a C-syntax style language, using { } to surround code and ; to terminate statements. Every app also has a unique main() function, which is the starting point of the application.

This is probably the shortest app possible, but it can be even shorter! The void keyword indicates (as in Java or C#) that the method does not explicitly return an object (indeed print only produces output to the console), but the return types can be left out. Furthermore, when a function has only one single expression, we can shorten this further to the following elegant shorthand syntax:

main() => print("Hello, World!");

Now, change the printed string to "Becoming a Dart Ninja!" and click on the green arrow button (or press Ctrl + R) to run the application. You should see something like the following screenshot (where the Files, Apps, and Outline items from the Tools menu were selected):

The Dart Editor

You have successfully executed your first Dart program!

Near the bottom of the screen, we see our string printed out together with the exit code=0 message meaning that all went well.

The Files and Apps tabs are useful for browsing through your applications and for creating, copying, moving, renaming, and deleting files. The Outline tab now only shows main(), but this tool will quickly become very useful because it provides an overview of the code in the active file.

Because this was a command-line application, we could just as easily have opened a console in our dart1 folder and executed the dart main.dart command to produce the same output as shown in the following screenshot:

A Dart console application

Note

To let this work, you must first let the OS know where to find the Dart V. For example, in Windows, you change the path environment variable to include C:\dart\dart-sdk\bin if your Dart installation lives in C:\dart.

 

Getting a view on the Dart tool chain


Dart comes with batteries included, which means that a complete stack of tools is provided by Google to write Dart apps, compile, test, document, and publish them. Moreover, these tools are platform-independent (being made for 32- and 64-bit Linux, OSX, and Windows) and they are integrated in the Dart Editor IDE. The Dart Editor contains everything a seasoned developer needs to work with confidence on his app:

  • Syntax coloring for keywords

  • Auto completion for class members (by typing . after a class name you get a list of available properties and methods of the current class)

  • Folding/unfolding code blocks

  • Tools to navigate the code (a handy overview of the code with the outline, find callers of a method, and so on)

  • Full debugging capabilities of both browser and server applications

  • Choose your preferred editor style by navigating to Tools | Preferences | Visual Theme

  • Quick fixes for common errors

  • Refactoring capabilities

  • Direct access to the online API documentation by navigating to Help | API Reference

The code you make is analyzed while you type, indicating warning (yellow triangles) or errors (red underscores or stop signs). To get more acquainted and experiment with these possibilities, go and read the documentation at http://www.dartlang.org/docs/editor/ and play with one of the samples such as Sunflower or Solar (you can find the samples by navigating to Tools | Welcome Page). From now on, use the editor in conjunction with the code examples of the book so that you can try them out and test the changes.

The Dart execution model

How a Dart app executes is sketched in the following diagram:

The Dart execution model

The Dart code produced in the Dart Editor (or in a plugin for Eclipse or IntelliJ) can:

  • Execute in the Dart VM, hosted in Dartium (Dartium is an experimental version of Chrome to test out Dart) or directly in the operating system (the browser VM knows about HTML, the server VM does not, but can use, for example, IO and sockets, so they are not completely equivalent)

  • Be compiled to JS with the dart2js compiler so that it can run in all the recent browsers

Code libraries in Dart are called packages and the Dart SDK core contains the basic types and functionalities to work with collection, math, html, uri, json, and so on. They can be recognized by the dart:prefix syntax, for example, dart:html. If you want to use a functionality from a library in a code file, you must import it by using the following as the first statement(s) in your code (dart:core is imported by default):

import 'dart:html';

The Dart code can be tested with the unit test package and, for documentation, you can use the dartdoc tool, which generates a local website structured like the official API documentation on the Web. The pub tool is the Dart package manager: if your app needs other packages besides the SDK, pub can install them for you (from the Tools menu item in Dart Editor, select Pub Get or Pub Update). You can also publish your apps with it in the http://pub.dartlang.org/ web repository.

We will see all of these tools in action in Chapter 2, Getting to Work with Dart.

 

A bird's eye view on Dart


It's time to get our feet wet by working on a couple of examples. All the code will be thoroughly explained step by step. Along the way, we will give you a lot of tips and, in the next chapter, we will go into more detail on the different possibilities, thus gaining deeper insight into Dart's design principles.

Example 1 – raising rabbits

Our first real program will calculate the procreation rate of rabbits, which is not only phenomenal but indeed exponential. A female rabbit can have seven litters a year with an average of four baby rabbits each time. So, starting with two rabbits, at the end of the year, you have 2 + 28 = 30 rabbits. If none of the rabbits die and all are fertile, the growth rate will follow the next formula, where n is the number of rabbits after the years specified:

n(years) = 2 x ek x years

Here, the growth factor k = ln(30/2) = ln15. Let's calculate the number after each year for the first 10 years.

Go to File | New Project as before, select Console application, and type the following code, or simply open the script from chapter_1 in the provided code listings (don't worry about the pubspec.yaml file, we'll discuss it in the web version).

The calculation is done in the following prorabbits_v1.dart Dart script:

import 'dart:math';                                      (1)

void main() {
  var n = 0; // number of rabbits                        (2)

  print("The number of rabbits increases as:\n");        (3)
  for (int years = 0; years <= 10; years++) {            (4)
    n = (2 * pow(E, log(15) * years)).round().toInt();   (5)
    print("After $years years:\t $n animals");           (6)
  }
}

Our program produces the following output:

The number of rabbits increases as:

After 0 years:    2 animals
After 1 years:    30 animals
After 2 years:    450 animals
After 3 years:    6750 animals
After 4 years:    101250 animals
After 5 years:    1518750 animals
After 6 years:    22781250 animals
After 7 years:    341718750 animals
After 8 years:    5125781250 animals
After 9 years:    76886718750 animals
After 10 years:  1153300781250 animals

So, if developing programs doesn't make you rich, breeding rabbits will. Because we need some mathematical formulas such as natural logarithms log and power pow, we imported dart:math in line (1). Our number of livestock n is declared in line (2); you can see that we precede its name with var. Here, we don't have to indicate the type of n as int or num (so called type annotations), as Dart uses optional typing.

Note

Local variables are commonly declared untyped as var.

We could have declared it to be of type num (number) or int, because we know that n is a whole number. However, it is not necessary, as Dart will derive this from the context in which n is used. The other number type is called double, used for decimal numbers. Also, the initialization part (= 0) could have been left out. With no initialization var n; or even int n;, it gives n the value null, because every variable in Dart is an object. The null keyword simply indicates that the object has no value yet (meaning that it is not yet allocated in heap memory). It will come as no surprise that // indicates the beginning of a comment, and /* and */ can be used to make a multiline comment.

Tip

Comment on a section of the code by selecting it and then right-click on Toggle comment in the Edit menu.

In the lines (3) and (6), we see that within a quoted string, we can use escape characters such as \n and \t to format our output. Line (4) uses the well-known for loop that is also present in Dart. In order to have the count of animals as a whole number, we needed to apply the round() function. The pow function produces double and because 6750.0 animals doesn't look so good, we have to convert double into int with the toInt() function. In the line (6), the elegant string substitution mechanism (also called string interpolation) is used: print takes a string as argument (a string variable: any expression enclosed within " " or ' ') and, in any such quoted string expression, you can substitute the value of variable n by writing $n. If you want the value of an expression within a string, such as a + b, you have to enclose the expression with braces, for example, ${a + b}.

Tip

You don't have to write ${n} while displaying a variable n, just use $n; you can also simply use print(n).

It is important to realize that we did not have to make any class in our program. Dart is no class junkie like Java or C#. A lot can be done only with functions; but if you want to represent real objects in your programs, classes is the way to go (see the Example 2 – banking section).

Extracting a function

This version of our program is not yet very modular, we would like to extract the calculation in a separate calculateRabbits(years) method that takes the number of years as a parameter. This is shown in the following code (version 2 line (4) of prorabbits_v2.dart) with exactly the same output as version 1:

import 'dart:math';

int rabbitCount = 0;                                   (1)
const int NO_YEARS = 10;                               (2)
const int GROWTH_FACTOR = 15;                          (3)

void main() {
  print("The number of rabbits increases as:\n");
  for (int years = 0; years <= NO_YEARS; years++) {
    rabbitCount = calculateRabbits(years);             (4)
    print("After $years years:\t $rabbitCount animals");
  }
}

int calculateRabbits(int years) {                      (5)
  return (2 * pow(E, log(GROWTH_FACTOR) * years)).round().toInt();
}

Tip

We could have written this new function ourselves, but Dart has a built-in refactoring called Extract Method. Highlight the line:

n = (2 * pow(E, log(15) * years)).round().toInt();

Right-click and select Extract Method. Dart will do the bulk of the work for you, but we can still simplify the proposed code by omitting the n parameter.

The calculateRabbits function calculates and returns an integer value; this is indicated by the int word preceding the function name. We give the function a return type here (int), but the program would have run without the function-type indication because of Dart's type inference.

This new function is called by main(). This is the way a Dart program works: all the lines in main() are executed in sequence calling functions, as needed, and the execution (and with it, the Dart VM) stops when the } ending of main() is reached. Things get a bit more complicated when Futures or Streams are used: these are put in a microtask queue to be executed. Only when there are no more tasks to execute in this queue will the Dart VM stop executing.

We rename the n variable to rabbitCount, so we need no more comments.

Tip

Renaming a variable is also a built-in refactoring. Select the variable (all the occurrences are then indicated), right-click, and then select Rename.

A good programmer doesn't like hardcoded values such as 10 and 15 in a program. What if they have to be changed? We replace them with constant variables indicated by the const keyword in Dart, whose name is, by convention, typed in capital letters and parts separated by _, see lines (2) and (3).

Tip

Take care of your top-level variables, constants, and functions, because they will probably be visible outside of your program (sometimes, called the interface or API of your program). Type them and name them well.

Now, for some practice:

  1. Examine this second version by going to Tools | Outline.

  2. Set a breakpoint on the rabbitCount = calculateRabbits(years); line by double-clicking on the margin in the front.

  3. Run the program and learn how to use the features of the Debugger tool (press F5 to step line by line, F6 or F7 to step over or out of a function, and F8 to resume execution until the next breakpoint is hit).

  4. Watch the values of the years and rabbitCount variables.

The output should resemble the following screenshot:

Debugging prorabbits_v2.dart

A web version

As a final version, for now, let us build an app that uses an HTML screen, where we can input the number of years of rabbit elevation and output the resulting number of animals. Go to File | New Project, but this time select Web application. Now, a lot more code is generated, which needs explaining. The app now contains a web subfolder; this will be the home for all of the app's resources. However, for now, it contains a stylesheet (.css file), a hosting web page (.html), and a startup code file (normally main.dart, in our case, prorabbits_v3.dart). The first line in this file makes the HTML functionality available to our code:

import 'dart:html';

We remove the rest of the example code, so only an empty main() function remains. Look at the source of the HTML page right before the </body> tag, it contains the following code:

<script type="application/dart" src="prorabbits_v3.dart"></script>
<script src="packages/browser/dart.js"></script>

The first line starts our Dart script.

The Dart VM exists only in Dartium for testing and debugging purposes. For other browsers, we must supply the Dart-to-JS compiled scripts; this compilation can be done in the Editor by navigating to Tools | Pub Build - Minified Javascript. The output size is minimal: the "dead" JS code that is not used is eliminated in a process called tree shaking. However, where does this mysterious script dart.js come from? The src="packages/browser/dart.js" value means that it is a package available in the Dart repository at http://pub.dartlang.org/.

External packages that your app depends on need to be specified in the dependencies section in the pubspec.yaml file. In our app, it contains (I have changed the name and description) the following:

name: prorabbits_v3
description: Raising rabbits the web way
dependencies:
  browser: any

We see that our app depends on the browser package; any version of it is ok. The package is added to your app when you right-click on the selected pubspec.yaml file and select Pub Get: a packages folder is added to your app and, per package, a subfolder is added containing the downloaded code, in our case, dart.js (In Chapter 2, Getting to Work with Dart, we will explore pub in greater depth and see that it can also be performed from the command-line).

For this program, we replace the HTML <p id="sample_text_id"></p> code as shown in the following code:

<input type="number" id="years" value="5" min="1" max="30">
<input type="button" id="submit" value="Calculate"/>
<br/>Number of rabbits: <label id="output"></label>

The input field with type number (new in HTML5) gives us a NumericUpDown control with a default value 5 limited to the range of 1 to 30. In our Dart code, we now have to handle the click-event at the button with id as submit. We do this in our main() function with the following line of code:

querySelector("#submit").onClick.listen( (e) => calcRabbits() );

The query Selector ("#submit") gives us a reference in the code to the button with ID equal to submit and listen redirects to an anonymous function (see Chapter 2, Getting to Work with Dart) to handle the e event, which calls the calcRabbits()function shown in the following code:

calcRabbits() {
  // binding variables to html elements:
  InputElement yearsInput  = querySelector("#years");        (1)
  LabelElement output = querySelector("#output");            (2)
  // getting input
  String yearsString = yearsInput.value;
  int years = int.parse(yearsString);  
  // calculating and setting output:
  output.innerHtml = "${calculateRabbits(years)}";
}

Here, in the lines (1) and (2), the input field and the output label are bound to the yearsInput and output variables. This is always done in the same way: the querySelector() function takes as its argument a CSS selector; in this case, the ID of the input field (an ID is preceded by a # sign). We typed yearsInput as InputElement (because it is bound to an input field). This way, we can access its value, which is always string. We then convert this string into an int type with the int.parse()function, because calculateRabbits needs an int parameter. The result is shown as HTML in the output label via string substitution, see the following screenshot:

The screen of prorabbits_v3

All the objects in the Dart code that are bound to the HTML elements are instances of the Element class. Notice how you can change the Dart and HTML code, and save and hit refresh in Dartium (Chrome) to get the latest version of your app.

Example 2: banking

All the variables (strings, numbers, and also functions) in Dart are objects, so they are also instances of a class. The class concept is very important in modeling entities in real-world applications, making our code modular and reusable. We will now demonstrate how to make and use a simple class in Dart by modeling a bank account. The most obvious properties of such an object are the owner of the account, the bank account number, and the balance (the amount of money it contains). We want to be able to deposit or withdraw an amount of money so as to increase or decrease the balance, respectively. This can be coded in a familiar and compact way in Dart, as shown in the following code:

class BankAccount {
  String owner, number;
  double balance;
  // constructor:
  BankAccount(this.owner, this.number, this.balance);    (1)
  // methods:
  deposit(double amount) => balance += amount;           (2)
  withdraw(double amount) => balance -= amount;
}

Notice the elegant constructor syntax in line (1), where the incoming parameter values are automatically assigned to the object fields via this. The methods (line (2)) can also use the shorthand => function syntax, because the body contains only one expression. If you prefer the {} syntax, they will be written as follows:

deposit(double amount) {
  balance += amount;
  return balance;
}

The code in main() makes a BankAccount object ba and exercises its methods (see the banking_v1.dart program):

main() {
  var ba = new BankAccount("John Gates", "075-0623456-72", 1000.0);
  print("Initial balance:\t\t ${ba.balance} \$");
  ba.deposit(250.0);
  print("Balance after deposit:\t\t ${ba.balance} \$");
  ba.withdraw(100.0);
  print("Balance after withdrawal:\t ${ba.balance} \$");
}

The preceding code produces the following output:

Initial balance:               1000.0 $
Balance after deposit:         1250.0 $
Balance after withdrawal:      1150.0 $

Notice how when you type ba. in the editor, the list of the BankAccount class members appears to autocomplete your code. By convention, variables (objects) and functions (or methods) start with a lower case letter and follow the CamelCase notation (http://en.wikipedia.org/wiki/CamelCase), while class names start with a capital letter as well as the word parts in the name. Remember Dart is case sensitive!

 

Making a to-do list with Dart


Since this has become the "Hello World" for web programmers, let's make a simple to-do list and start a new todo_v1 web application. To record our tasks, we need an input field corresponding with InputElement in Dart:

<input id="task" type="text" placeholder="What do you want to do?"/>

The HTML5 placeholder attribute lets you specify a default text that appears in the field.

We specify a list tag (UListElement), which we will fill up in our code:

<ul id="list"/>

The following is the code from todo_v1.dart:

import 'dart:html';

InputElement task;
UListElement list;

main() {
  task = querySelector('#task');             (1)
  list = querySelector('#list');             (2)
  task.onChange.listen( (e) => addItem() );  (3)
}

void addItem() {
  var newTask = new LIElement();             (4)
  newTask.text = task.value;                 (5)
  task.value = '';                           (6)
  list.children.add(newTask);                (7)
}

We bind our HTML elements to the Dart objects task and list in the lines (1) and (2). In line (3), we attach an addItem event handler to the onChange event of the textfield task: this fires, when the user enters something in the field and leaves it (either by pressing Tab or Enter). UListElement is, in fact, a collection of LIElements (these are its children). So, for each new task, we will make LIElement in (4), assign the task's value to it in (5), clear the input field in (6), and add the new LIElement to the list in (7). In the following screenshot, you can see some tasks to be performed:

A simple to-do list

Of course, this version isn't very useful (unless you want to make a print of your screen); our tasks aren't recorded and we can't indicate the tasks are finished. Don't worry, we will enhance this app in the future versions.

 

Summary


We covered a lot of ground in this introductory chapter but, by now, you know the reasons for using Dart in the context of web applications. We also saw where Dart apps can live, how they are executed, and the various tools to work with Dart, in particular, the Dart Editor.

You also got acquainted with some simple command-line and web Dart apps and got a feeling for the Dart syntax. In the next chapter, we will explore the various code and data structures of Dart more systematically. Any obscurities that are still there in your mind will surely disappear. More coming soon to a Dart center near you...

About the Authors

  • Ivo Balbaert

    Ivo Balbaert has been a lecturer in web programming and databases at CVO Antwerpen, a community college in Belgium. He received a Ph.D. in applied physics from the University of Antwerp in 1986. He worked for 20 years in the software industry as a developer and consultant in several companies, and for 10 years as project manager at the University Hospital of Antwerp. From 2000 onwards, he switched to partly teaching and partly developing software (at KHM Mechelen, CVO Antwerpen). He also wrote an introductory book in Dutch about developing in Ruby and Rails, Programmeren met Ruby en Rails, by Van Duuren Media. In 2012, he authored a book on the Go programming language, The Way To Go, by IUniverse. He wrote a number of introductory books for new programming languages, notably Dart, Julia, Rust, and Red, all published by Packt.

    Browse publications by this author
  • Dzenan Ridjanovic

    Dzenan Ridjanovic is a university professor who is planning his early retirement to focus on the development of web applications with Dart, HTML5, web components, and NoSQL databases. For more than 10 years, he was a director of research and development in the Silverrun team (http://www.silverrun.com/), which created several commercial tools to analyze, design, and develop data-driven applications. He was the principal developer of Modelibra tools and frameworks for model-driven development in Java. Currently, he is developing the dartling framework for the design and code generation of Dart models. His projects are on GitHub (https://github.com/dzenanr), where he is considered a Dart expert. He writes about his projects on the On Dart blog (http://dzenanr.github.io/). His courses are available on On Dart Education (http://ondart.me/). He markets his Dart efforts on the On Dart G+ page (https://plus.google.com/+OndartMe). Dzenan Ridjanovic wrote a book in 2009, under the Creative Commons License, entitled Spiral Development of Dynamic Web Applications: Using Modelibra and Wicket.

    Browse publications by this author

Latest Reviews

(3 reviews total)
The purchase of my eBooks & Videos was through PayPal & instant download but I had to go through answering my physical billing & shipping address? I should have been taken straight to PayPal and the provided with the email downloads only. That would be a speedier purchase experience.
I am really impressed that something as good as "Learning Dart" could get even better ! keep up the good work
Some of the examples weren't connected as well to previous examples.
Learning Dart - Second Edition
Unlock this book and the full library FREE for 7 days
Start now