-
Notifications
You must be signed in to change notification settings - Fork 89
Building Something More than "Hello World"
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.
###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.
###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.