More and more web application is adopting "Single Page Application (SPA)" style to improve user experience (UX). There are many different SPA framework out there, however AngularJS leading by Google really stand out, not only because it can dramatically reduce the developing effort, but also it can improve the maintainability, testability and efficiency. In this tutorial, it will demonstrates the fundamentals features of AngularJS with easy to follow sample pages. All the source code could be found on GitHub: https://github.com/erhwenkuo/PracticalCoding
2. Document, Source code & Training
Video
• https://github.com/erhwenkuo/PracticalCoding
3. References
• The training material of this session are base on
Dan Wahlin’s terrific “AngularJS Fundamentals
in 60-ish Minutes”
• https://www.youtube.com/watch?v=i9MHigUZ
KEM
4. Agenda
• AngularJS Introduction
• Getting Started & Features
• Directives, Filters and Data Binding
• Views, Controllers and Scope
• Modules, Routes and Factories
7. Feeling About AngularJS Over Time
1. Neat
What? This is so lame!
2. Ok, that’s pretty sweet!
I can’t believe how difficult they
make some of this stuff! Are you
kidding me?!
3. Very Cool!
We’ve made a horrible choice! We
should went with Backbone.
4. OMG, that’s awesome!
Better freshen up the old resume.
5. Most awesome framework ever!
12. The Challenge with SPAs
DOM Manipulation
Routing
Caching
Data Binding
History Module Loading
Object Modeling
Ajax/Promises
View Loading
13. AngularJS is a full-featured SPA
framework
Data Binding MVC Routing Testing
jqLite Templates History Factories
ViewModel Controllers Views Directives
Services Dependency Injection Validation
14. Developing Environment & Source Tree
Configure the Machine
• .NET Framework 4.51
• Visual Studio 2013 (Update 4)
Source Tree Folder Structure
• doc : Contains documents related to
the code base
• lib : Contains all third-party and
packages used by the application,
including NuGet downloaded
packages
• src : Contains all the source code,
including Visual Studio file(s) and all
project folders
PracticalCoding
doc
lib
src
15. Developing Environment & Source Tree
Creating The Solution Folder Structure
• Create a “Blank Solution” named “PracticalCoding” in
Visual Studio
• Close Visual Studio and copy “PracticalCoding.sln” to
“src” folder
• Delete the empty folder
• Use text editor to create “nugget.config” file with
below content under “src” folder
PracticalCoding
doc
lib
src
PracticalCoding.sln
Nugget.config
16. Developing Environment & Source Tree
• Use File explorer to open
“PracticalCoding.sln” file
• Add new “ASP.NET Web
Application” project under
“PracticalCoding” solution in
Visual Studio
• Name this web project to
“PracticalCoding.Web”
• Click “OK”
18. Developing Environment & Source Tree
Setup AngularJS
1. Download most update AngularJS
from https://angularjs.org
2. Unzip and rename to “angular”
3. Copy and paste to C# project
under “/Scripts” folder
4. Include the whole
“/Scripts/angular” folder into C#
project
22. Using Directives and Data Binding
Syntax (step_01_blankpage.html)
Demo Page
1. Create “MyApp” folder
2. Create
“01_DirectivesAndDataBinding”
folder under “MyApp”
3. Add new html file named
“step_01_blankpage.html”
4. Drag “angular.js” from “Scripts”
folder inside”<body></body>”
23. Using Directives and Data Binding
Syntax (step_02_normalpage.html)
Demo Page
1. Copy “step_01_blankpage.html” as “step_02_normalpage.html
2. Add a simple html “input” tag
3. Hit “F5” and see the result
24. Using Directives and Data Binding Syntax
(step_03_adddirectivedatabind.html)
Demo Page
1. Copy
“step_02_normalpage.html”
as
“step_03_adddirectivedatabi
nd.html ”
2. Add “ng-app” as attribute
within “<html>” tag
3. Add “ng-model=‘vm.name’”
within “<input>” tag
4. Add “{{vm.name}}” after
“<input>” tage
5. Hit “F5” and see the result
25. Iterating with the ng-repeat
Directive
1. “ng-init” is the angular directive to initialize some data
2. “ng-init” is the angular directive to iterate collection of data
26. Iterating with the ng-repeat
Directive(step_04_iteratewithngrepeat)
Demo Page
1. Copy
“step_03_adddirectivedatabind.html”
as “step_04_iteratewithngrepeat.html ”
2. Add “ng-init=….” as attribute in <body>
tag and add “ng-repeat” as attribute in
<li> tag.
3. Add angular expression
“{{personName}} ” to show binding
value
4. Hit “F5” and see the result
28. Using Filters
Filter in AngularJS is not only used to filter data, but also it can be used to format
data for display as well
29. Iterating with the ng-repeat
Directive(step_05_nginitcustomers)
Demo Page
1. Copy
“step_04_iteratewithngrepeat.html
” as
“step_05_nginitcustomers.html”
2. Change “ng-init=…. “ to initialize a
array of Customer objects
3. Change “ng-repeat” to iterate this
new customers collection. And
Change angular expression
“{{customer.name}} -
“{{customer.city}} ” to show binding
value
4. Hit “F5” and see the result
30. Iterating with the ng-repeat
Directive(step_06_filterbyinputandformat)
Demo Page
1. Copy “step_05_nginitcustomers.html” as “step_06_filterbyinputandformat.html”
33. AngularJS View, Controllers & Scope
1. $scope is the “glue” (ViewModel) between a controller and a view
2. The view don’t have to know about the controller
3. The controller definitely doesn’t want to know about the view
View $scope Controller
34. AngularJS View, Controllers &
$scope(step_07_simplecontroller)
Demo Page
Copy “step_06_filterbyinputandformat.html” as “step_07_simplecontroller.html”
Assign view to specific
controller
$scope is
injected
ng-repeat access the
vm.customers via
$scope
40. AngularJS Module and Controllers
(step_07_simplecontroller)
Demo Page
step_07_simplecontroller.html
Assign view to specific
controller
$scope is
injected
43. AngularJS Define Routes Demo
(step_08_defineroutes)
Demo Page
Copy “step_07_simplecontroller.html” as “step_08_defineroutes.html”
Include “angular-route.
js”
Using
“$routeProvider” to
define routes
Add one <div> with
“ng-view” inside
46. AngularJS Define Routes Demo
(step_08_defineroutes)
Demo Page
Select “step_08_defineroutes.html” and Hit “F5” to run
47. AngularJS Define Routes Demo
(step_09_addcustomer)
Demo Page
Copy “step_08_defineroutes.html” as “step_09_addcustomer.html”
Create a new
variable for
newCustomer
Add a new method
“addCustomer()”
under
“SimpleController”
Create a new
variable for
newCustomer
Define routings
48. AngularJS Define Routes Demo
(step_09_addcustomer)
Demo Page
Copy“Partials_step_08” to “Partials_step_09” & Modify “View1.html”
Binding input to
newCustomer
Use “ng-click” to call
“addCustomer()” method
49. AngularJS Define Routes Demo
(step_09_addcustomer)
Demo Page
Select “step_09_addcustomer.html” and Hit “F5” to run
50. Using Factories and Services
Controller
Config
Routes
Module
Filter Directives Factory
Service
Provider
Value
52. AngularJS Factory Demo
(step_10_factorytogetcustomer)
Demo Page
1. Copy “step_09_addcustomer.html” as “step_10_factorytogetcustomer.html”
2. Add AngularJS factory “SimpleFactory”
Create a new factory
“SimpleFactory“
Define a javascript
object instance for
return
Create a new
variable for
newCustomer
Define factory
own variables and
methods for
external access
53. AngularJS Factory Demo
(step_10_factorytogetcustomer)
Demo Page
Return javascript
object instance
Create a new
variable for
newCustomer
Define factory
own variables and
methods for
external access
54. AngularJS Factory Demo
(step_10_factorytogetcustomer)
Use “SimpleFactory”
to access shared
methods or
attributes
The agenda is…
We’re going to start off with some of the key features AngularJS offers and I’ll kind of introduce the challenge with writing SPAs from scratch.
Anyone who knows me knows I do not recommend writing them from scratch. I just think that in the long term it is, when it comes to maintenance, a nightmare.
There’s too many scripts involved and I’m worried about version dependencies and scripts changing and things breaking.
So we’re going to talk about that and how Angular addresses it.
Then we’re going to get started with some of the framework fundamental features that Angular provides.
Then I’ll go into some of those key features that you’ve really got to start off with, kind of the A-B-Cs of Angular if you will, so Directives, Filters and two-way Data Binding which is just awesome.
I’m a big fan of some of the other scripts out there – like KnockoutJS as an example - but you’re going to see that Angular is a true framework. It’s not just a library that does maybe one or two things: it actually can do a LOT of different things.
Once we get through the Directives, Filters and Data Binding we’re going to talk about Views, Controllers and Scope.
And then we’ll wrap up with Modules, and we’ll talk about how all this other stuff fits into modules, and then we’ll get into some SPA concepts like Routes and even Factories for sharing data and using data.
累的時候, 放鬆一下。
待會兒再回來看的時候, 說不定你就會變成 “Wow~!這太棒了!”
AngularJS truly in my opinion is an awesome framework and so a lot of light bulbs went off. Once that started happening all the pieces fitted in and made total sense to me.
I think it’s like anything. With a new framework: sometimes you catch it instantly when you learn it, and other times you don’t.
What I’m going to do throughout this video is walk you through all the key things that I wish I would have understood more about upfront and hopefully jump-start your AngularJS development process.
First off, a Single Page Application is one in which we have a shell page and we can load multiple views into that.
So a traditional app, as you know you typically blink and load everything again. It’s not very efficient on the bandwidth, especially in the mobile world.
In a SPA we can load the initial content upfront and then the different views or the little kind of mini- web pages can be loaded on the fly and embedded into the shell.
AngularJS, as we’re going to see, is a very good SPA framework, but it’s not just for that. You don’t have to load these dynamic views with it.
The challenge with building SPAs from scratch is there’s a lot of different issues to deal with: DOM manipulation and history and how do you dynamically load modules and how do you deal with promises when you make async calls and things like that.
Routing becomes a huge issue because you have to have some way to track “Where are we? And where are we going?”
All of this type of stuff you’re going to see is built into Angular. Now we can certainly do all this with different scripts out there. We could use sammyJS and jQuery and historyJS and requireJS. For AJAX we can use Q and there’s a lot of different options.
But Angular, you’re going to see, provides a lot of cool features.
It does all kinds of good stuff.
We have two-way data binding. We have the Model-View-Controller concept. Routing of the Views I mentioned into the shell pages is done through built-in routing support and I’ll show how to do that in this video.
Testing was designed right from the beginning so you can build very robust tests if you’d like, which is obviously recommended.
For DOM manipulation jQLite is built-in which is kind of like the Mini-Me of jQuery.
If you want to use more advanced stuff you can even use jQuery and they play really nice together: Angular and jQuery.
When it comes to data binding we have full support for templates.
History’s built in.
We can share code through factories and services and other things.
Then there’s even more. We have the concept of data-binding with View Models.
Directives I’m going to be talking about in the next section, which is a way to teach HTML new tricks.
Validation.
Dynamically injecting different features at run time through dependency injection and much much more.
為了降低學習上的困難, 在這一系列的課程中我們會使用Microsoft的Visual Studio 2013(Update 4)來做為開發的IDE
為了降低學習上的困難, 在這一系列的課程中我們會使用Microsoft的Visual Studio 2013(Update 4)來做為開發的IDE
To start off, what is a directive?
Well I mentioned this earlier.
A directive is really a way to teach HTML new tricks.
The web when it first came out was really just designed to display static pages.
As we all know it’s become very dynamic and we’ve dealt with that pretty well.
jQuery came out many years ago and it provided a way to do it.
Even before then we could use raw, vanilla JavaScript.
Angular takes it up a whole notch and allows us to extend HTML very easily by simply adding attributes, elements or comments.
Here’s an example of using a very basic, but important, Angular directive.
Notice at the top we have ng-app. Any time you see ng- that is an Angular directive. It’s a built-on directive. You can also write custom ones. You can get third party ones and things like that.
This particular directive is very important because the script that’s now loaded [at the bottom] is going to kick off and this will initialise the Angular app. Right now we don’t have any particular module associated or any other code but we can still do stuff just by adding ng-app.
So for example, this is an example of another directive called ng-model.
What ng-model does is behind the scenes it’s going to add a property up in the memory called “name” into what’s called “the scope”.
If you’ve ever dealt with the concept of a View’s model called a ViewModel - Knockout and some other libraries have this concept – then what this is really doing behind the scenes is making an empty ViewModel but then filling it with a name property. Now if I want to write out that value then I can simply come over and add a data binding expression.
Expressions are really cool because if I wanted to put “1 + 1” and try to write out the result I could do that. You can’t put conditional logic in here because you shouldn’t be putting that type of conditional logic in your views. But out of the box, just b
So let’s go ahead and look at a demonstration of that. y adding the ng-app and ng-model with a property as they type into this text box I can actually bind to that value and that provides a very cool little feature.
You can see that as I type it automatically binds it, and that’s pretty damned easy, right?
Include the ng-app
Include the ng-model
Bind to that model.
This is pretty primitive and we’re going to go much deeper here, but that’s how we can get started.
Let’s say that as we bind to, say a customer name, and we do that process we want to upper-case it. Now I could upper-case it in my data model, which we’ll get to in a little bit later, but an easy way to do this type of thing is to apply an AngularJS filter.
In this part of the tutorial we’re going to talk about Views, Controllers and a really integral part of Angular called Scope, which is really another term for ViewModel if you’ve used that term before.
The way it works in Angular is you have a View, which is what we’ve been doing in the previous section with our Directives, our Filters and our Data Binding.
But we don’t want to put all of our logic into the View because it’s not very maintainable or testable or all those types of things.
Instead we’re going to have a special little JavaScript object – a container - called a Controller. The Controller will drive things. It’s going to control ultimately what data gets bound into the View. If the View passes up data to the controller it will handle passing off maybe to a service which then updates a back-end data store.
The glue between the View and the Controller is something called the Scope, and in Angular you’re going to see a lot of objects or variables that start with $. $scope represents the scope object.
Here’s an example of a really simple controller called, oddly enough, SimpleController. You’ll notice an interesting thing here in the parameter signature. You’ll see that we pass $scope. This is dependency injection that’s built into AngularJS
The way it works in Angular is you have a View, which is what we’ve been doing in the previous section with our Directives, our Filters and our Data Binding.
But we don’t want to put all of our logic into the View because it’s not very maintainable or testable or all those types of things.
Instead we’re going to have a special little JavaScript object – a container - called a Controller. The Controller will drive things. It’s going to control ultimately what data gets bound into the View. If the View passes up data to the controller it will handle passing off maybe to a service which then updates a back-end data store.
The glue between the View and the Controller is something called the Scope, and in Angular you’re going to see a lot of objects or variables that start with $. $scope represents the scope object.
Now that you’ve seen data binding, directives, filters and controllers, and you’ve seen how the scope actually can integrate between a view and a controller it’s now time to really move it up a notch and talk about modularity and some more SPA-oriented concepts like routes.
In this section we’re going to talk about how to create modules, and how modules can actually be used to create other things like controllers, routes, factories and services, and how all this fits together.
當我開始學習AngularJS的時候, 曾經有一度我覺得相當掙扎,後來歸咎原因, 最主要是我沒有一開始就先對Angular的結構及它相關的元件是如何相互協同運作的部份做一個整體的了解。
在這裡我會秀出一個AngularJS結構的簡圖, 當然它有可能太過於簡化AngularJS了, 但是它讓我可以快速的理解AngularJS。
一個AngularJS的模組(Module)可以呼叫一個config的function。
It can be defined to use different routes. Now routes again are really important in the SPA world because if you have different views and those views need to be loaded into the shell page then we need a way to be able to track what route we’re on and what view that’s associated with and then what controller goes with that view and how we do all of that marrying together of these different pieces.
When you define a route in AngularJS you can define two things on that route – two of the key things, I should say.
One of those is the view. So what view when that route such as “unit.org/orders” then maybe go to “orderspartial.html” or “ordersfragment.html” or whatever you want to call it.
Then that view needs a controller. Instead of hard-coding the controller into the view – which works and you can certainly do it: I showed that in the previous section – we can actually go in and do this on our own through the route. This is the way I would definitely recommend you do it.
A given controller would then of course have access to the scope object which then the view will bind to. I talked about that a little bit earlier.
And then controllers rather than having all the functionality to get the data and update the data and perform CRUD operations and things like that, in a more real life application they’ll call out to factories or… I put a star there because you might have services, providers or even values you want to get. There are a lot of different ways you can access data. Even resources.
On the views we of course then have directives and filters and those types of things.
There’s even more to the overall picture but this is one of those things I wish I would’ve seen this right upfront because I would have kind of instantly had that light bulb moment where the light goes on and you say “OK. So you define a route, a route has a controller and a view and then the controller can load data from factories and services and things.”
What we’re going to do is talk about each of these individual pieces and how in a single page application you can actually define routes and use those.
Here’s an example of a really simple controller called, oddly enough, SimpleController. You’ll notice an interesting thing here in the parameter signature. You’ll see that we pass $scope. This is dependency injection that’s built into AngularJS
Now once you’ve defined a module and a controller, at some point if you’re building a single page application you’re going to need routes because we need to load different views into our shell page.
This will be an example of four different routes.
We have when View1 is clicked maybe there’s a link to it and that link is something like “/view1”. Typically you have a hash but you’ll see that coming up. That will load that view. Then when they click on a link that has View2 in the path then that would load up View2 but it’s not going to load up the whole shell page. Angular will only load up the page that you want.
There’s two kind of ways you can load it.
First off, the view could be embedded as a script template in the actual shell page and then we could just tell Angular “Heh! The template id to load… it’s kinda like saying ‘The view id is x’”.
The second way is back up on the server you might actually have all these Views and I like to call them “partials” because they’re part of a page. You can tell Angular “the template URL for what I want to load” and then you give it the URL to the server, and I’m going to show that coming up here.
This is a really important feature because we want to be able to go in and load different partials or fragments and then that will be kind of how our SPA works.
What we’re going to do is use that config that I showed earlier.
We have angular.module is “demoApp” with no dependencies.
Now what I’m going to do is configure the module with some routes. Another object that’s available in Angular is called the routeProvider, as you can see here. It’s kind of like the scope – it’s injected in dynamically just by defining $routeProvider as your parameter.
In this case we’re going to say “For the routeProvider when the route is just a slash “/” to the root we want to use SimpleController with View1.html. When the route is “/partial2” we want to use the same controller in this case but you can certainly do a different one, with a template URL of View2.
Now the template URL: you might give it a folder where these partials are going to live, and I actually like to call my folder “partials” but you don’t have to.
Otherwise if it [the route] doesn’t mean any of those routes we’re going to redirect back to the root, which ultimately goes back up to here [the “/” route specified with the first “.when” statement] which will load View1.
Here’s an example of a really simple controller called, oddly enough, SimpleController. You’ll notice an interesting thing here in the parameter signature. You’ll see that we pass $scope. This is dependency injection that’s built into AngularJS
Here’s an example of a really simple controller called, oddly enough, SimpleController. You’ll notice an interesting thing here in the parameter signature. You’ll see that we pass $scope. This is dependency injection that’s built into AngularJS
Here’s an example of a really simple controller called, oddly enough, SimpleController. You’ll notice an interesting thing here in the parameter signature. You’ll see that we pass $scope. This is dependency injection that’s built into AngularJS
Here’s an example of a really simple controller called, oddly enough, SimpleController. You’ll notice an interesting thing here in the parameter signature. You’ll see that we pass $scope. This is dependency injection that’s built into AngularJS
最後我們會來看看AngularJS 對於re-use 的概念上的實現。
Another feature of AngularJS is the ability to encapsulate data functionality into factory, services, provider or little value providers.
I’m going to focus on factories here but all three of the top ones shown here – factory, service and providers – they allow us to encapsulate common functionality.
So for instance if I had to go and get customers and I need those customers in multiple controllers I wouldn’t want to hard code that data in each controller. It just wouldn’t make sense and there’d be a lot of duplication there.
Instead what I’ll do is I’ll move that code out to a factory, service or provider.
The difference between the three is just the way in which they create the object that goes and gets the data. That’s really all there is to it.
With the factory you actually create an object inside of the factory and return it.
With the service you just have a standard function that uses the this keyword to define function.
With the provider there’s a $get you define and it can be used to get the object that returns the data.
A value is just a way to get for instance a config value. A simple example of this you’ll see on the Angular site is you might just want the version of a particular script. So you’d have a name-value pair where the name of the value might be “version” and then the value might be say “1.4”
I’m not going to cover all those here but I am going to cover factories. So let’s take a look at how we can use a module to define a factory.