- AngularJS Tutorial
- AngularJS Views And Directives
- AngularJS $scope Hierarchy
- AngularJS Events
- AngularJS $watch() , $digest() and $apply()
- AngularJS AJAX
- AngularJS Forms
- AngularJS $timeout and $interval
- AngularJS Custom Directives
- AngularJS Modularization & Dependency Injection
- AngularJS Routes
- AngularJS Internationalization
- AngularJS Critique
AngularJS AJAX
Jakob Jenkov |
AngularJS AJAX Introduction
In AngularJS you can send AJAX requests in several different ways. These are:
- AJAX calls via the
$http
service. - JSONP calls via the
$http
service. - REST type calls.
Note: So far only the $http
service is covered (both normal AJAX and JSONP), but that is enough
to get you started using AJAX in AngularJS. The REST API is not necessary to understand to start using AJAX
(and personally I am not that big a fan of it - you can do the same just as easily with the $http
service).
The $http Service
The $http
service is the easiest way to send AJAX calls to your web server.
Remember, that AJAX calls cannot be sent to a different domain than the domain from
which the HTML page making the AJAX calls is loaded. For instance, if the HTML page
was loaded from jenkov.com then that HTML page can only make AJAX calls back to URLs
within the jenkov.com domain.
Here is a full AngularJS application with a single $http
AJAX example:
<!DOCTYPE html> <html lang="en"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script> </head> <body ng-app="myapp"> <div ng-controller="MyController" > <button ng-click="myData.doClick(item, $event)">Send AJAX Request</button> <br/> Data from server: {{myData.fromServer}} </div> <script> angular.module("myapp", []) .controller("MyController", function($scope, $http) { $scope.myData = {}; $scope.myData.doClick = function(item, event) { var responsePromise = $http.get("/angularjs-examples/json-test-data.jsp"); responsePromise.success(function(data, status, headers, config) { $scope.myData.fromServer = data.title; }); responsePromise.error(function(data, status, headers, config) { alert("AJAX failed!"); }); } } ); </script> </body> </html>
Notice how the controller function registered with the module takes two parameters:
A $scope
object (as always) and an extra $http
object.
The $http
object (or "service") is used to make AJAX calls.
The the $http.get()
function returns a "promise" object.
This promise object has a success()
and an error()
function. By calling these functions and pass a function to them as parameter
you can control what happens when the AJAX call finishes. If the AJAX call
succeeds (the server sends back an HTTP code between 200 and 209), the function passed to the success()
function is
executed. If the AJAX call fails (all other codes except for redirects), the function passed to the error()
method is executed. The succss()
and error()
functions are covered in more
detail later.
$http Functions
The $http
service has several functions you can use to send AJAX
requests. These are:
$http.get(url, config)
$http.post(url, data, config)
$http.put(url, data, config)
$http.delete(url, config)
$http.head(url, config)
Notice that the $http.post()
and $http.put()
functions take a data
parameter which contains data to be sent to the server. The rest of the $http
functions cannot take
a data parameter.
The data
parameter will be converted to a JSON string. This string will be be included in
the request body when the HTTP request is sent to the server. AngularJS will consider all properties
starting with a $
as private, and thus exclude these from the string. If you need
to include properties starting with a $
in the data string, convert the data
object to a string yourself using JSON.stringify(data)
.
$http as a Function
You can also use the $http
service as a function directly, like this:
var promise = $http(config);
In this case the URL and HTTP method are also set inside the config
object.
The config
object is explained in the following section.
The config Parameter
The config
parameter passed to the different $http
functions controls the
HTTP request sent to the server. The config
parameter is a JavaScript object which can
contain the following properties:
method
url
params
headers
timeout
cache
transformRequest
transformResponse
The method
property can be used to set the HTTP method for pthe request. The method is
one of either GET, POST, PUT, DELETE
or HEAD
. This property is normally
set implicitly via the function you choose to call on the $http
service, so you will
rarely need to set this property in practice.
The url
property can be used to set the URL of the AJAX call. This is already provided
to the various $http
functions, so you will rarely need to set this again in the config
object.
The params
property is used to set any additional request parameters to be appended
to the URL query string. The params
property is a JavaScript object with one property
per request parameter to add.
The headers
property is used to set any additional HTTP headers you want sent to the
server. The headers
property is a JavaScript object with one property per header.
The timeout
property is used to set the timeout for the AJAX call. When the timeout
limit is reached, the AJAX call is aborted. The timeout is specified in milliseconds.
The cache
property is used to enable XHR GET request caching.
The transformRequest
property is used to set a function which can transform the
request object before it is sent to the server.
The transformResponse
property is used to set a function which can transform
the response sent back from the server, before it is passed to your application.
The success() And error() Functions of The Promise Object
As mentioned earlier the various AJAX functions on the $http
service return a promise object.
This promise object has two functions called success()
and error()
. Each of these
two functions take a callback function as parameter. If the AJAX request succeeds, the callback function
passed to the success()
function is executed. If the AJAX request fails, the callback function
passed to the error()
function is called.
Inside the success()
and error()
function you should set the appropriate
values on the $scope
object. That is the way to get the data or error message out
to the user. Update the $scope
object with data, and AngularJS will trigger the
HTML template rendering so the data can be made visible to the user.
Both functions take the following parameters:
data
status
headers
config
The data
parameter is the JSON object returned by the server. The $http
service
assumes that your server sends back JSON.
The status
parameter is the HTTP status code returned by the server along with the response.
The headers
parameter is a function that can be used to obtain any HTTP response headers
returned along with the response. You get a header by calling headers([headerName]);
. As you
can see, the headers()
function take an array of header names as parameter. The
AngularJS documentation is a bit vague about what the function returns, but I suspect it returns a JavaScript object
with one key, value pair for each header, with the header name as the key (property name).
The config
parameter is the configuration object that was used to create the given HTTP request (AJAX call).
In other words, the config
object which was passed as parameter to the $http
ajax function
call that created this AJAX call, and thereby this promise object.
AngularJS & JSONP
AngularJS's $http
service is also capable of sending JSONP requests. The normal AJAX calls
can only send requests to URLs within the same domain as the HTML page sending the requests was loaded from.
You can get around this with JSONP requests.
JSONP is short for "JSON with Padding" (I explain why, later). A JSONP request is not sent via the XHR object like AJAX calls
normally are. Instead, a <script>
element is created and inserted into the HTML page.
Here is an example of how such a <script>
element could look:
<script src="http://jenkov.com/theService.json?callback=theServiceResponse&p1=v1&p2=v2"></script>
The src
attribute contains the URL of the remote service to call with the JSONP call.
This URL should include any parameters you need to send to the remote service.
When the <script>
element is inserted into the HTML page, the browser will load
the script from the given URL. That enables the remote service to send JavaScript back to your application
for execution.
The JavaScript returned by the remote service should be a function call to an existing JavaScript function in your HTML page. Here is how the returned JavaScript could look:
theServiceResponse( { name : "John", title : "CEO", company : "BigFatCo" } );
This code makes a function call to the function named theServiceResponse
. This function must
be present in your HTML page already. Inside this function you process the response sent back from the
service.
When the theServiceResponse()
function is called, a JavaScript object is passed to
the function as parameter. This JavaScript object contains the response parameters from the service call.
Thus, this JavaScript object is generated by the remote service. Whatever the remote service wants
to send back to you is what this JavaScript object contains. Seen from the remote service's perspective,
that JavaScript object is just JSON like any other JSON sent back to an HTML page. The difference is
that this JSON object is wrapped in a function call. This function call is the "padding" part of the
"JSON with Padding" name for JSONP.
You might wonder how the remote service knows the name of the function to wrap the returned JSON in.
The answer is, that you pass that name to the remote service along with the other request parameters.
The function name is one of the request parameters. By default this parameter name is callback
but you will have to check with the concrete service to see what parameter name it expects for the function name.
In AngularJS the function name is supplied behind the scene by AngularJS, so you don't have to worry about adding it to the URL of the remote service.
You use JSONP calls via the $http
service like this:
$http.jsonp( url, config );
Like with the AJAX functions the jsonp()
function takes a url
and a config
object. Here is an example of a JSONP call with the url
and config
objects supplied:
var url = http://jenkov.com/theService.json?callback=JSON_CALLBACK"; var responsePromise = $http.jsonp( url, { params : { p1 : "v1" ,p2 : "v2" } } ); responsePromise.success(function(data) { // do something with the returned JavaScript object // ( in the "data" parameter ). });
This example makes a JSONP call to the service URL http://jenkov.com/theService.json
.
Like with the other AJAX functions of the $http
service, the config
object
can contain a params
field. This field should be a JavaScript object containing all the
request parameters to append to the URL of the remote service.
When you call the $http.jsonp()
function AngularJS will create <script>
element for you, and insert it into your HTML page. AngularJS will also create the final URL of the
remote service by appending the parameters passed in the config.params
object to the
URL.
The URL passed to the $http.jsonp()
function must contain the callback=JSON_CALLBACK
parameter. AngularJS will replace the JSON-CALLBACK
string with the name of a callback function
which AngularJS creates.
The promise object returned by the $http.jsonp()
function has a success()
function, just like the other AJAX function call promise objects. Unfortunately we do not have
access to the HTTP headers of the response sent back from the server, since that request is handled
by the browser internally, when evaluating the <script src="url">
element.
That also means that if the JSONP call fails, we have no way of knowing so, since no callback function
will get called in that case (no JavaScript to execute from the remote service).
JSONP Security
You have to be careful with JSONP calls. When you make a JSONP call. The remote service could send back any JavaScript which would then get executed inside your HTML page. An evil remote service could send back JavaScript which attempts to steal information from your application and sent it to a third party service. Only make JSONP calls to services you trust.
Tweet | |
Jakob Jenkov |