asciidoc AngularJS Web应用程序中的XHR拦截器

AngularJS Web应用程序中的XHR拦截器

angularinterceptor.adoc
XHR Interceptor in an AngularJS web app
=======================================

Origin: http://blog.brunoscopelliti.com/xhr-interceptor-in-an-angularjs-web-app
 
We’ll start by looking at how to define an interceptor.

The following code must to be placed inside the config section of the web app (the only place of your app 
where the service providers are accessible).

``` javascript
$httpProvider.interceptors.push(['$q', function($q) {
	return {
		
		/* All the following methods are optional */

		request: function(config) {
			/*
			  Called before send a new XHR request.
			  This is a good place where manipulate the
			  request parameters.
			*/

			return config || $q.when(config);
		},

		requestError: function(rejection) {
			// Called when another request fails.

			// I am still searching a good use case for this.
			// If you are aware of it, please write a comment

			return $q.reject(rejection);
		},

		response: function(response) {
			// Called before a promise is resolved.

			return response || $q.when(response);
		},

		responseError: function(rejection) {
			/*
			  Called when another XHR request returns with
			  an error status code.
			*/

			return $q.reject(rejection);
		}
	}
}]);
```

Now that it’s clear how to create XHR interceptor, let’s take a look at why we should use XHR interceptor 
in a web application.

XHR request interceptor
-----------------------

It may surprise some readers, but by default in AngularJS the payload of a POST request is always in JSON format. 
This means that, for example, if PHP is your backend language, you won’t find any data in your $_POST array. 
Instead, you can use the PHP function file_get_contents to read the payload.

``` javascript
if(stripos($_SERVER["CONTENT_TYPE"], "application/json") === 0) {
	$data = json_decode(file_get_contents("php://input"), true);
}
```

All this pain can be avoided with the savvy use of request interceptors.
To achieve this, first change the default content-type header used by AngularJS 
(need more info about request header?).
This should do the trick:

``` javascript
$http.defaults.headers.post["Content-Type"] 
  = "application/x-www-form-urlencoded; charset=UTF-8;";
// You could place this everywhere; the only condition is 
// that the $http service is in that scope.
```

We can then use the request interceptor to encode the payload:

``` javascript
$httpProvider.interceptors.push(['$q', function($q) {

	return {
		request: function(config) {
			if (config.data && typeof config.data === 'object') {

				/*
				  Before the request starts, the interceptor serializes
				  the data object as a string.
				*/

				config.data = serialize(config.data);
				// Check https://gist.github.com/brunoscopelliti/7492579 
				// for a possible implementation of the serialize function.

			}
			return config || $q.when(config);
		}
	};
}]);
```

XHR response interceptor
------------------------

In my experience response interceptors are particularly helpful to handle specific error case.
In my previous post about XHR interceptors, I wrote about how to intercept a 401 (Unauthorized) error response.
Let’s rewrite that example with this new approach.

``` javascript
$httpProvider.interceptors.push(['$q', function($q) {

	return {
		response: function(response) {
			// response.status === 200
			return response || $q.when(response);
		},
		responseError: function(rejection) {
			// Executed only when the XHR response has an error status code

			if (rejection.status == 401) {

				// The interceptor "blocks" the error;
				// and the success callback will be executed.

				rejection.data = { stauts: 401, description: 'unauthorized' }
				return rejection.data;
			}

			/*
			  $q.reject creates a promise that is resolved as
			  rejected with the specified reason. 
			  In this case the error callback will be executed.
			*/
			
			return $q.reject(rejection);
		}
	}
}]);
``` 

asciidoc ngscope.adoc

ngscope.adoc
AngularJS Scopes: An Introduction
=================================

Tommy Fisher, http://blog.carbonfive.com/2014/02/11/angularjs-scopes-an-introduction/

Angular Scopes
--------------

AngularJS has a fair share of deep concepts; taking some time to understand them can get you back on track.

One of these important concepts is scopes. In an AngularJS application, the controller and view share an object 
called a scope; this object is at the core of its amazing two-way data binding. The controller sets properties 
on the scope, and the view binds to those properties. AngularJS takes responsibility for keeping the two in sync.

Let’s start with a simple example:

``` Javascript
app.controller('SimpleController', function($scope) {
    $scope.message = 'Hello Angular!';
});
```

``` HTML
<div ng-controller="SimpleController">
    <input ng-model="message">
    <span>{{message}}</span>
</div>
```

``` text
Hello Angular!
```

In this example, the controller sets a property, message, on the scope. When AngularJS processes the ng-model
directive in the view, it starts listening for change events on that input element and on the scope’s message
property. If the value of message changes, the input will update, and if the input changes, message updates. 
Let’s look at another example:
	
``` js
app.controller('HelloController', function($scope) {
    $scope.message = 'Hello World!';
});

app.controller('GoodbyeController', function($scope) {
    $scope.message = 'Goodbye World!';
});
```

``` HTML
<div ng-controller="HelloController">
    <input ng-model="message">
    <span>{{message}}</span>
</div>
<div ng-controller="GoodbyeController">
    <input ng-model="message">
    <span>{{message}}</span>
</div>
```

``` text
Hello World!
Goodbye World!
```

Even though both inputs bind to a message property, they’re completely independent because they are bound to 
separate scopes. But where do those scopes come from?

Sidebar: Scope Creation
-----------------------

When your application starts, AngularJS creates the initial scope, which it calls $rootScope. 
It then “compiles” the document, starting at the root element. As it traverses the DOM, it encounters and 
processes markers that it calls directives, and some of these (such as ng-controller) request new scopes. 
After compilation is done, AngularJS will have created a scope tree that mirrors the DOM tree – 
the $rootScope is bound to the root element and child scopes are bound as the DOM nodes that request them 
are discovered.

Separate scopes are incredibly useful. As seen in the example above, they allow for different parts of the 
view to cleanly separate their part of the underlying model. Additionally, child scopes can access properties 
of their parent, for example:

``` javascript
app.controller('OuterController', function($scope) {
    $scope.outer = 'From the outside';
});

app.controller('InnerController', function($scope) {
    $scope.inner = 'looking in.';
});
```

``` HTML
<div ng-controller="OuterController">
    <div ng-controller="InnerController">
        {{outer}}, {{inner}}
    </div>
</div>
```

``` text
From the outside, looking in.
```

But how does this work? We know from the earlier example that each controller has a separate scope created for it, 
and, as far as we can tell, the inner controller’s scope has no outer property on it.

Sidebar: AngularJS Scope Inheritance
------------------------------------

In JavaScript, classical inheritance doesn’t exist. However, each object has a special property, called its 
prototype. When accessing properties of an object, if the property doesn’t exist, JavaScript checks if it 
exists on the prototype. It will continue looking up the prototype chain until it finds the property or it 
reaches the end.

AngularJS uses object prototypes to implement child scopes. When creating a new scope, by default, it sets 
the new scope’s prototype to its parent. This scope inheritance allows us to create pages with nested components, 
as seen in the example above. However, sometimes the interaction between parent and child scopes can be confusing:
	
``` HTML
<div ng-controller="EditController">
    <span>{{message}}</span>
    <div ng-if="userIsAdmin">
        <span>Edit Message</span>
        <input ng-model="message"/>
    </div>
</div>
```

``` javascript
app.controller('EditController', function($scope) {
    $scope.userIsAdmin = true;
    $scope.message = 'Redact me';
});
```

``` text
Redact me
Edit Message
```

At a first glance, we expect this code to work – but when we try to edit the message, we notice it’s not being 
updated above. Why?

Just like ng-controller, the ng-if directive creates a child scope, and it’s that child scope that ng-model is 
binding to. Before we modify the input, no message property exists on the child scope, so the prototype chain is 
consulted, and the parent’s message is used. However, when we update the input, ng-model sets the message property 
on the child. The end result is two separate message properties on the parent and child scope, not what we intended!

We can verify this was the problem by explicitly referring to the parent scope within the child:
	
``` html
<div ng-controller="EditController">
    <span>{{message}}</span>
    <div ng-if="userIsAdmin">
        <span>Edit Message</span>
    <input ng-model="$parent.message"/>
    </div>
</div>
```

``` text
Redact me
Edit Message
```

Here, we tell ng-model instead to bind to $parent.message and we never end up creating message locally in 
the child. Although this code works, it’s highly suspect. Because it uses $parent, if we make a simple 
change to our view, by changing ng-if to ng-show (which doesn’t create a new scope), our scope hierarchy 
would change and our code would suddenly break. A better alternative is to bind to properties of objects:

``` html
<div ng-controller="EditController">
    <span>{{message.content}}</span>
    <div ng-if="userIsAdmin">
        <span>Edit Message</span>
        <input ng-model="message.content"/>
    </div>
</div>
```

``` javascript
app.controller('EditController', function($scope) {
    $scope.userIsAdmin = true;
    $scope.message = {
        content: 'Redact me'
    };
});
```

``` text
Redact me
Edit Message
```

This example works because AngularJS now looks for message, then content. Since message refers to an object 
on the parent, content is never set on the child scope. It’s a best practice to never bind directly to 
primitives to avoid this problem.

Isolating Scopes
----------------

AngularJS’s default scope inheritance model can be very useful to divide up parts of a large application, but 
sometimes it causes problems. In particular, it’s very difficult to write reusable components – how can you 
ensure your code works when you can’t know what scope it will be included in?

Luckily, AngularJS provides an escape hatch from inheritance: isolated scopes. These scopes are identical to 
normal ones – but they do not prototypically inherit. Isolated scopes can only be used in directives, so let’s 
create a simple one:
	
``` javascript
app.directive('isolated', function() {
    return {
        scope: {},
        template: '<input ng-model="message.content"><span>{{message.content}}</span>'
    };
});
```

``` html
<div ng-controller="EditController">
    <input ng-model="message.content">
    <span>{{message.content}}</span>
    <div isolated></div>
</div>
```

``` text
I'm on the outside
```

Our directive uses scope: {}, which tells AngularJS to create an isolated scope. We also inline a template, 
which will be inserted into the DOM when we use the directive. Even though the template refers to the parent 
scope’s message.content, it cannot access it, because it’s bound to the directive’s isolated scope.

Isolated scopes are great for encapsulation, but without some kind of communication with a parent, their use 
is very limited. To address this, AngularJS provides a way to bind specify properties between the isolated 
scope and its parent:
	
``` javascript
app.directive('isolated', function() {
    return {
        scope: {
            message: '='
        },
        template: '<input ng-model="message.content"><span>{{message.content}}</span>'
    };
});
```

``` html
<div ng-controller="EditController">
    <input ng-model="parentMessage.content">
    <span>{{parentMessage.content}}</span>
    <div isolated message="parentMessage"></div>
</div>
```

``` text
Now I can get in
Now I can get in
```

This example makes it seems like both inputs share the same scope – but they don’t. In our isolated scope 
definition, message: '=' sets up a two-way binding between the parent’s parentMessage and the child’s message 
properties. Using bindings like this is a common way to pass values to an isolated scope, or to allow it to 
set a value on its parent.

Summary
-------

Scopes are core to how AngularJS works, so understanding them is very important. Learning how to use scopes 
effectively helps you better divide up chunks of large applications, and using isolated scopes can help you 
encapsulate complex components.

Although we’ve barely scratched the surface, we now know enough to dive deeper. If you’re looking to learn 
more, explore how AngularJS keeps the view in sync with the digest loop, or learn how to communicate directly 
between scopes with events.

asciidoc 角度指令 - 鲜为人知

角度指令 - 鲜为人知

angular-directives.adoc
Lesser know AngularJS directives
================================

by http://djds4rce.wordpress.com/2013/10/20/lesser-know-angularjs-directives/[djds4rce]


Lesser know AngularJS directives
--------------------------------

One of the most awesome things in angular is its approach towards creating reusable HTML attributes and elements 
through ‘Directives’.  Along with letting you write your own custom directives, angular ships with a lot of default
directives.  While some are helpers like ng-show,ng-class others like ng-model and ng-src are bound with angular internals. 

This blog post is a list of a few lesser known yet useful directives.

These along with many other built in angular directives give us a hint of what angular project philosophy is and where it 
is heading towards: Making Common UI events more declarative, reusable and decoupled from the application logic.


ng-if
-----

From an aesthetic point ng-if works similar to ng-show and ng-hide, but instead of hiding the Dom element it selectively 
adds or removes it from the DOM tree based on whether the expression supplied it true for false. This is use full because
unlike hide and show, the removed element will not be collected when using css selectors.

ng-class-even/ng-class-odd
--------------------------

While in ng-repeat, we can selectively add classes to the repeated element based on whether the index of the element is odd
or even.

Bonus:$index gives the index of the element in the iterator.

ng-change
---------

ng-change lets you to trigger a function or evaluate a expression when the text changes in the particular text box. 
For the ng-change to work, the text box should be binded to a model.

ng-dbclick
----------

db-click handles double click events within an element and lets you invoke a function or evaluate a expression when it 
is done.

similar:ng-mousedown,ng-keypress.

ng-style
--------

Lets you add inline styles to your elements. although inline styles are evil and should be avoided, this cool as you can dynamically update
your style attribute values based on a model binding.

ng-pluralize
------------

The pluralize directive lets you pluralize your content based on en-US localization rules.

Example

[source,html]	
--
<span>
    {{group.members_count}} 
    <ng-pluralize count='group.members_count'.when="{'1': 'Member','other':'Members'}">
</span>
--

Based on the value of members_count. member or members is rendered.

ng-cloak
--------

When the browser renders HTML if AngularJS is not loaded completly, the bindings will show up as very ugly curly braces.
This directive acts as blanket from displaying angular binding syntax before Angular JS is loaded into the browser.
Using this directive in your main pages is a must.

similar:ng-href