You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Now it's time to make the web page dynamic — with AngularJS.
20
+
21
+
This step will still be focusing on client side Angular tools. the next one will show you how to get the power of Meteor.
22
+
23
+
There are many ways to structure the code for an application. For Angular apps, we encourage the use of the Model-View-Controller (MVC) design pattern to decouple the code and to separate concerns. With that in mind, let's use a little Angular and JavaScript to add model, view, and controller components to our app.
24
+
25
+
Goals for this step:
26
+
27
+
* The list of three parties is now generated dynamically from data in the model of the client
28
+
29
+
30
+
# View and Template
31
+
32
+
In Angular, the view is a projection of the model through the HTML template. This means that whenever the model changes, Angular refreshes the appropriate binding points, which updates the view.
33
+
34
+
The view component is constructed by Angular from this template:
35
+
36
+
__`index.html`:__
37
+
38
+
<divng-controller="PartiesListCtrl">
39
+
<ul>
40
+
<ling-repeat="party in parties">
41
+
[[party.name]]
42
+
<p>[[party.description]]</p>
43
+
</li>
44
+
</ul>
45
+
</div>
46
+
47
+
48
+
We replaced the hard-coded phone list with the [ngRepeat](https://docs.angularjs.org/api/ng/directive/ngRepeat) directive and two Angular expressions:
49
+
50
+
* The ng-repeat="party in parties" attribute in the li tag is an Angular repeater directive. The repeater tells Angular to create a li element for each party in the list using the li tag as the template.
51
+
* The expressions wrapped in double-square-brackets ([[party.name]] and [[party.description]]) will be replaced by the value of the expressions.
52
+
53
+
We have added a new directive, called ng-controller, which attaches a PartiesListCtrl controller to the div tag. At this point:
54
+
55
+
* The expressions in double-square-brackets ([[party.name]] and [[party.description]] denote bindings, which are referring to our application model, which is set up in our PartiesListCtrl controller.
56
+
57
+
58
+
# AngularJS app
59
+
60
+
Now we are going to create our own AngularJS client app with client controller and model.
61
+
62
+
First, let's create our app.
63
+
64
+
Create a new app.js file. now you can see another example of Meteor's power and simplicity - no need to include this file anywhere. Meteor will take care of it by going through all the files in the folder and including them automaticly.
65
+
66
+
But Meteor's goal is to break down the barrier between client and server, and the code you write runs everywhere! (more on that later).
67
+
But we need Angular's power only in the client side, so how can we do that?
68
+
69
+
There are a few ways to tell Meteor to run a code only on the client/server/phone side, let's start with the simplest way - Meteor.isClient variable.
70
+
71
+
__`app.js`:__
72
+
73
+
if (Meteor.isClient) {
74
+
75
+
}
76
+
77
+
Now anything that will happen inside this if statement will run only on the client side.
78
+
79
+
So let's continue with starting our AngularJS applicantion, we will call it "socially":
80
+
81
+
__`app.js`:__
82
+
83
+
if (Meteor.isClient) {
84
+
angular.module('socially',['ngMeteor']);
85
+
86
+
Meteor.startup(function () {
87
+
angular.bootstrap(document, ['socially']);
88
+
});
89
+
}
90
+
91
+
What we did here is to declare a new angular module named 'socially' and making it dependant on the 'ngMeteor' module (that we included in the first step).
92
+
93
+
Then we told our applicantion to start our angular module applicantion on startup.
94
+
95
+
96
+
# Model and Controller
97
+
98
+
Now let's create our PartiesListCtrl controller and place data in it.
'description': 'Fast just got faster with Nexus S.'},
116
+
{'name': 'All dubstep all the time',
117
+
'description': 'Get it on!'},
118
+
{'name': 'Savage lounging',
119
+
'description': 'Leisure suit required. And only fiercest manners.'}
120
+
];
121
+
122
+
}]);
123
+
}
124
+
125
+
126
+
Here we declared a controller called PartiesListCtrl and registered it in our AngularJS module app, 'socially'.
127
+
The controller is simply a constructor function that takes a $scope parameter.
128
+
129
+
The data model (a simple array of parties in object literal notation) is now instantiated within the PartiesListCtrl controller.
130
+
131
+
Although the controller is not yet doing very much, it plays a crucial role. By providing context for our data model, the controller allows us to establish data-binding between the model and the view. We connected the dots between the presentation, data, and logic components as follows:
132
+
133
+
* The ngController directive, located on the body tag, references the name of our controller, PartiesListCtrl (located in the JavaScript file app.js).
134
+
135
+
* The PartiesListCtrl controller attaches the party data to the $scope that was injected into our controller function. This scope is a prototypical descendant of the root scope that was created when the application was defined. This controller scope is available to all bindings located within the div ng-controller="PartiesListCtrl"> tag.
136
+
137
+
# Scope
138
+
139
+
The concept of a scope in Angular is crucial. A scope can be seen as the glue which allows the template, model and controller to work together. Angular uses scopes, along with the information contained in the template, data model, and controller, to keep models and views separate, but in sync. Any changes made to the model are reflected in the view; any changes that occur in the view are reflected in the model.
140
+
141
+
To learn more about Angular scopes, see the [angular scope documentation](https://docs.angularjs.org/api/ng/type/$rootScope.Scope).
142
+
143
+
144
+
# Experiments
145
+
146
+
Add another binding to index.html. For example:
147
+
148
+
<p>Total number of parties: [[parties.length]]</p>
149
+
150
+
Create a new model property in the controller (inside app.js) and bind to it from the template. For example:
151
+
152
+
$scope.name = "World";
153
+
154
+
Then add a new binding to index.html:
155
+
156
+
<p>Hello, [[name]]!</p>
157
+
158
+
Verify that it says "Hello, World!".
159
+
160
+
Create a repeater in index.html that constructs a simple table:
161
+
162
+
<table>
163
+
<tr><th>row number</th></tr>
164
+
<trng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>[[i]]</td></tr>
165
+
</table>
166
+
167
+
Now, make the list 1-based by incrementing i by one in the binding:
168
+
169
+
<table>
170
+
<tr><th>row number</th></tr>
171
+
<trng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>[[i+1]]</td></tr>
172
+
</table>
173
+
174
+
Extra points: try and make an 8x8 table using an additional ng-repeat.
175
+
176
+
# Summary
177
+
178
+
You now have a dynamic app that features separate model, view, and controller components.
179
+
180
+
But, this is all client side, which is nice for tutorials but in a real application we need to save the data in a DB on the server and sync all the clients with it.
181
+
182
+
So, let's go to step 3 to learn how to bind ourselves to the great power of Meteor.
0 commit comments