Angular $http
Objectives
- Use $http to access an API resource
- Use $scope.$watch to observe model changes
What is $http?
$http
is a core Angular service provided for you to use. It allows the browser to send HTTP requests and responses, similar to AJAX calls in jQuery.
Using $http
We can use the $http
service to request data from an external source. $http
can be incorporated into an Angular app via dependency injection. This can happen on either the module or controller.
In our example, we'll include $http
as a dependency for each controller. Specifically, we'll be using $http
to access a public API that allows Cross Origin Resource Sharing (CORS).
Getting Started
Take a look at the sample code, which should have scaffolds for index.html
and js/app.js
. Add the following to app.js
:
var movieApp = angular.module('MovieApp', []);
movieApp.controller('SearchCtrl', ['$scope', '$http', function($scope, $http) {
}]);
Yes, we are making yet another OMDB app. This time, with Angular.
So let's setup what we'll need to perform a request to OMDB.
- A method to search for a movie (form input)
- A model to store the search term
- A URL to send the term to (OMDB)
- A function to receive and process the response
First, let's setup the form and model. (don't forget to setup ng-app
and ng-controller
first)
In index.html
<h1>Movie App</h1>
<form class="form" ng-submit="search()">
<div class="form-group">
<label>Search for a Movie:</label>
<input type="text" class="form-control" ng-model="searchTerm">
<input type="submit" class="btn btn-primary">
</div>
</form>
We'll see that we created a model called searchTerm
bound to the input field, and a function called search()
to execute when the form submits.
Now for the controller. Inside the SearchCtrl
within js/app.js
:
$scope.searchTerm = '';
$scope.search = function() {
var req = {
url: 'http://www.omdbapi.com',
method: 'GET',
params: {
s: $scope.searchTerm,
}
}
$http(req).then(function success(res) {
//do something with the response if successful
console.log(res);
}, function error(res) {
//do something if the response has an error
console.log(res);
});
};
We just added a variable called searchTerm
to $scope
, as well as added the search()
function. We also created an object to store the URL and search params (those search params will be converted to a querystring by $http
).
Lastly, we call $http
to perform a request with the req
object, then expect success and error callbacks. Try running this code and see what res
contains. Note that res
is the entire response, and we need to call res.data
to access the payload of the response.
Rendering Movies
In order to render movies to the page, we need to attach the data received to $scope
. Let's add a movies
variable to the controller's scope, and assign the data if the response is OK:
$scope.movies = [];
$http.get(req).then(function success(res) {
if (res.status === 200) {
$scope.movies = res.data.Search;
}
console.log(res);
}, function error(res) {
console.log(res);
});
Note that we obtain res.data.Search
because the response is an object with a key called Search
. The value associated with this key has our results.
Printing them out requires ng-repeat
in index.html
<div class="well" ng-repeat="movie in movies track by $index">
{{movie}}
</div>
You'll see that each movie
is an object. Take a few minutes and clean this up so each well displays the title and poster of each movie.
Related: Use ng-src
when including Angular markup in an image link. It's a common problem that pops up. Link to the ngSrc documentation.
$watch
So far, we've been having our views update when changes are made to the model. What if we want to "listen" to our model and have our controller react to changes? We can use $watch
in order to observe and react to model changes. For example, maybe we want the movie search to happen when the user changes the searchTerm
value.
// attaching a $watch function to $scope, defining two values:
// 1. The value to watch
// 2. A function that runs when the value changes, with the new and old values
$scope.$watch('searchTerm', function(newVal, oldVal) {
// perform the search here
});
Note that this works for expressions, but not collections (like objects and arrays). For objects and arrays, you can take advantage of $watchGroup
and $watchCollection
. Documentation is here.