Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Building Something More than "Hello World"

Kathy Walrath edited this page Jan 28, 2014 · 4 revisions

In the previous chapter, we showed you how to build a “Hello World” app. Now let’s do something more interesting. Let’s build a Recipe Book app.

###What you will learn In this tutorial, you will learn more about how Angular does MVC. Specifically, you will learn about controllers, which you will implement with something called an Angular controller. You will also learn more about the model, which Angular calls the scope.

When you’re finished, you will be able to write your own custom controller and use it to control the view. You will understand how to create data in the model, expose it through the controller, and access it from the view.

###Running the sample app The code for this chapter is in the Chapter_02 directory of the angular.dart.tutorial download. View it in Dart Editor by using File > Open Existing Folder... to open the Chapter_02 directory.

Now run the app. In Dart Editor's Files view, select Chapter_02/web/index.html, right-click, and choose Run in Dartium.

Dartium launches, displaying the first version of the Recipe Book app. Play with the app a bit by clicking on each recipe and watching it display in the view.

Dartium running the first Recipe Book app       Recipe Book with a recipe selected

###Understanding scopes In previous chapter, we alluded to the scope and provided a partial definition. In this chapter, we provide a more complete picture of scopes in Angular.

A scope in Angular is an execution context, and is similar to the idea of a scope or block in other programming languages. Each scope has its own context that is separate from the surrounding scopes.

There isn’t just one scope in an Angular app. At any given moment, there is a hierarchy of scopes that roughly mimics the DOM's structure. The ng-app directive declares the boundary of the root scope. Angular objects within the ng-app can create their own scopes called child scopes. Child scopes implicitly inherit the properties of their parents, but the properties defined in a child scope are not visible to the parent scope.

The diagram below shows how some relevant portions of the HTML template map to the Model/Scope, and how it’s represented in the view.

scopes

###Understanding the model In the previous chapter, we gave a simplified definition of the model (The model is the scope). In this chapter, we will give a more accurate definition. The model is defined as any property, function, or object that is reachable from the scope.

There are several ways that Model objects can be created in the scope. In the previous example, we showed you how to create and use a model object directly in the view, with code patterns like this:

<input type="text" ng-model="name">

Properties created in this way are created in the root scope, and not in the scope of the controller. These properties are available in the view, but are not directly available from inside the controller. Creating model data in this way is useful for demonstrating basic concepts in tutorials, but in practice it is not recommended.

The correct way to create model objects is to create a controller class and expose the controller to the view through a directive.

###Understanding controllers Traditional MVC defines a controller as an object that contains all the model data and methods necessary to control the view. Angular has three kinds of MVC controllers: controllers, directives, and components. These are implemented using plain old Dart classes. These plain old Dart classes are annotated as either an NgController, NgDirective or NgComponent, and the combination of the controller class and the annotation is analogous to an MVC controller. Controllers are the simplest of the three types of controllers, so we will cover them first. We will cover directives and components in the next chapters.

###Understanding controller The easiest way to create a controller is to put the NgController annotation on a controller class and then declare the controller class as a type in the bootstrap module.

In the Recipe Book example, we see this annotation on the RecipeBookController class:

@NgController(
    selector: '[recipe-book]',
    publishAs: 'ctrl')

This annotation tells Angular that the class RecipeBookController is an Angular controller. When the compiler sees one of these in the DOM, it instantiates the controller class.

Controllers are configured by setting properties on the annotation. Here we describe the most common properties.

#####selector The required selector field defines the CSS selector that will trigger the controller. It can be any valid CSS selector which does not cross element boundaries.

#####publishAs The publishAs field specifies that the controller instance should be assigned to the current scope under the name specified. The controller’s public fields are available for data binding from the view through the publishAs name. Similarly, the controller’s public methods can be invoked from the view using the publishAs name. Here is an example:

<div><strong>Name: </strong>{{ctrl.selectedRecipe.name}}</div>

<li ng-click="ctrl.selectRecipe(recipe)">{{recipe.name}}</li>

Here we also see how to tell the Angular bootstrapping code about our custom types. Angular uses dependency injection to instantiate the application classes you create. Inside the ngBootstrap method, a new AngularModule is created. The AngularModule provides all of Angular’s built in services and directives. Your app’s module is added to the list of modules that Angular loads.

class MyAppModule extends Module {
  MyAppModule() {
    type(RecipeBookController);
  }
}

main() {
  ngBootstrap(module: new MyAppModule());
}

Including your controller class in the module allows Angular to instantiate the controller we just created.

From the view, we can use the controller by adding a set of attributes to the element which will trigger the CSS selector declared on the controller:

  <div recipe-book></div>

Anything within the containing element has access to the controller’s scope.

###Angular features In this chapter, we introduced you to two more built in Angular directives: ng-repeat and ng-click.

####ng-repeat Now that you have a better understanding of scopes, let’s elaborate on them further by describing what’s going on behind the scenes with the ng-repeat tag.

    <ul>
      <li class="pointer"
          ng-repeat="recipe in ctrl.recipes"
          ng-click="ctrl.selectRecipe(recipe)">{{recipe.name}}</li>
    </ul>

The ng-repeat directive on the li element causes Angular to iterate over the model (the recipes property in the RecipeBookController), and clone the li in the compiled DOM for each recipe in the list. Each li is created with its own scope and its own instance of the recipe property. If the model changes (for example, if a recipe is added to or deleted from the model), the ng-repeat tag re-evaluates the model and updates the view automatically.

####ng-click ng-click is a built-in Angular directive that allows you to specify custom behavior when any element is clicked. In our example, it invokes the selectRecipe() method on the controller, passing it the recipe property from the view.

Home | Prev | Next