$http response is undefined in angularJS - angularjs

I am having some problems, I appear to be getting the data in the callback but can't seem to get to it, to be honest I'm not entirely sure what is going on.
When I click the "Get Movie" button, I get the following in the console:
Error: response is undefined
app</$scope.addBook#http://onaclovtech.com/apps/movies/:42:1
Wa.prototype.functionCall/<#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:162:14
Mc[c]</<.compile/</</<#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:178:390
zd/this.$get</h.prototype.$eval#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:101:134
zd/this.$get</h.prototype.$apply#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:101:399
Mc[c]</<.compile/</<#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:178:370
Xc/c/<#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:27:145
q#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:7:357
Xc/c#https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js:27:129
When I look at the network tab after the button press I get the following:
http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[api-key]&q=The%20Way%20Of%20The%20Gun&page_limit=1&callback=angular.callbacks._0
When I look at the debugger I get a movies.json response object that looks like this:
angular.callbacks._0(
{"total":1,"movies":[{"id":"15775","title":"The Way of the Gun","year":2000,"mpaa_rating":"R","runtime":119,"critics_consensus":"","release_dates":{"theater":"2000-09-08","dvd":"2001-06-19"},"ratings":{"critics_rating":"Rotten","critics_score":48,"audience_rating":"Upright","audience_score":71},"synopsis":"","posters":{"thumbnail":"http://content7.flixster.com/movie/11/17/79/11177993_tmb.jpg","profile":"http://content7.flixster.com/movie/11/17/79/11177993_tmb.jpg","detailed":"http://content7.flixster.com/movie/11/17/79/11177993_tmb.jpg","original":"http://content7.flixster.com/movie/11/17/79/11177993_tmb.jpg"},"abridged_cast":[{"name":"Ryan Phillippe","id":"162676004","characters":["Parker"]},{"name":"Benicio Del Toro","id":"162652510","characters":["Longbaugh"]},{"name":"James Caan","id":"162656402","characters":["Joe Sarno"]},{"name":"Juliette Lewis","id":"162654115","characters":["Robin"]},{"name":"Taye Diggs","id":"162655514","characters":["Jeffers"]}],"alternate_ids":{"imdb":"0202677"},"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies/15775.json","alternate":"http://www.rottentomatoes.com/m/way_of_the_gun/","cast":"http://api.rottentomatoes.com/api/public/v1.0/movies/15775/cast.json","reviews":"http://api.rottentomatoes.com/api/public/v1.0/movies/15775/reviews.json","similar":"http://api.rottentomatoes.com/api/public/v1.0/movies/15775/similar.json"}}],"links":{"self":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=The+Way+Of+The+Gun&page_limit=1&page=1"},"link_template":"http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"}
)
So the data all appears to be there, I am just having a hard time figuring out how to get it.
Could someone help point me in the direction of getting the data correctly?
(I do plan to move the angularjs controller to a .js file eventually, but for now it's in the .html file, sorry)
This is my original code:
Index.html
<!DOCTYPE html>
<html ng-app="myapp" manifest="covers.appcache">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.min.js"></script>
<script src="https://cdn.firebase.com/js/client/1.0.11/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/0.7.1/angularfire.min.js"></script>
<script src="rottentomatoes.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style type="text/css">
<!--
/* Move down content because we have a fixed navbar that is 50px tall */
body {
padding-top: 50px;
padding-bottom: 20px;
}
-->
</style>
<!-- Optional theme -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
</head>
<body ng-controller="MyController">
<div align="left">
<button type="button" class="btn btn-primary btn-lg active" ng-click="addBook()">Get Movie</button>
</div>
<br />
<div>
{{data}}
{{success}}
<script>
var app = angular.module("myapp", ["video"])
.controller('MyController', ['$scope', '$video', function($scope, $video) {
$scope.addBook = function(e) {
var response = $video.search('[api-key]', 'The Way Of The Gun', '1');
response
.success(function(data, status) {console.log('SUCCESS' + data); $scope.data = data; $scope.status = status;})
.error(function(data, status) {console.log('ERROR' + status); $scope.data = data; $scope.status = status;});
// Found somewhere that said I needed a jsonp_callback function, I just tried it to see if it did anything, doesn't appear to
function jsonp_callback(data) {console.log('JSONP' + data); $scope.data = data; };
}
}]);
app.config(function($httpProvider) {
//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
});
</script>
</body>
</html>
rottentomatoes.js
angular.module('video', []).factory('$video', ['$http', function($http) {
return {
search: function(api_key, query, page_limit) {
var method = 'JSONP';
var url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?";
$http({
method: method,
url: url + "apikey=" + api_key +
"&q=" + query +
"&page_limit=" + page_limit + '&callback=JSON_CALLBACK'
});
}
};
}]);

In the $video.search() method, you return nothing hence the error occurred.
You could just return the $http() call like this and it should work:
angular.module('video', []).factory('$video', ['$http', function($http) {
return {
search: function(api_key, query, page_limit) {
var method = 'JSONP';
var url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?";
return $http({
method: method,
url: url + "apikey=" + api_key +
"&q=" + query +
"&page_limit=" + page_limit + '&callback=JSON_CALLBACK'
});
}
};
}]);
As general tips:
use an unminified angular.js instead of angular.min.js while debugging, it will give you more meaningful errors.
no need to define the jsonp_callback function, angular will handle that for you
avoid naming your own service with a $ prefix i.e. $video. The $ prefix is preserved for anything that built-in in the angularjs.

Related

converting an ajax request to angular $http

I'm learning how to use angular and I'm not really that familiar with making request to an api. I'm trying to practice using http://api.football-data.org/index. The json data I wanted to get from my angular factory is http://api.football-data.org/v1/competitions/426/leagueTable. Right now I'm getting an error in the console
'angular.js:13920 TypeError: Cannot read property 'getLeagueData' of undefined at new ...'
My CLI shows that I am loading all my script files and I tested my controller before trying to bring in the factory and creating the getLeagueData function and it was working so I know my issue is after creating the basic controller. I thought it might have to do with my headers needing the authentification token I received but I'm not sure if I haven't added it correctly. Here is my code
HTML
<!DOCTYPE html>
<html lang="en" ng-app='bplApp'>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title><%= title %></title>
<!-- Bootstrap -->
<link href="/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<!--Font Awesome-->
<link rel="stylesheet" href="/bower_components/font-awesome/css/font-awesome.min.css">
<!--Custom-->
<link rel='stylesheet' type='text/css' href='/stylesheets/main.css'>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class='leagueCheck' ng-controller='tableController as table'>
<div class='container'>
<div class='row'>
<div class='col-xs-12'>
{{table.test}}
</div>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src='/bower_components/angular/angular.min.js'></script>
<!--Module-->
<script src='bplApp.js'></script>
<!--Controller-->
<script src='/controllers/tableController.js'></script>
<!--Service-->
<script src='/services/footballData.js'></script>
Module
var app = angular.module('bplApp',[]);
Controller
app.controller('tableController', ['$scope', 'footballData', function($scope, footballData){
var self = this;
self.test = 'is working';
self.leagueStats = [];
footballData.getLeagueData().then(function(data){
self.leagueStats = data;
console.log(self.leagueStats);
})
}])
Factory
app.factory('footballData', [function($http){
return {
getLeagueData: function(){
return $http({
method: 'GET',
url: 'http://api.football-data.org/v1/competitions/426/leagueTable',
headers:{
'X-Auth-Token': '3e629af30fce46edaa6ead20e007a276'
}
})
}
}
}])
The original ajax code sample that the api shows for using it looks like this
$.ajax({
headers: { 'X-Auth-Token': 'YOUR_API_TOKEN' },
url: 'http://api.football-data.org/v1/fixtures?timeFrame=n1',
dataType: 'json',
type: 'GET',
}).done(function(response) {
// do something with the response, e.g. isolate the id of a linked resource
var regex = /.*?(\d+)$/; // the ? makes the first part non-greedy
var res = regex.exec(response.fixtures[0]._links.awayTeam.href);
var teamId = res[1];
console.log(teamId);
});
You used the array notation at your factory. Either use it directly or declare the $http in the array:
app.factory('footballData', ["$http", function($http){
return {
getLeagueData: function(){
return $http({
method: 'GET',
url: 'http://api.football-data.org/v1/competitions/426/leagueTable',
headers:{
'X-Auth-Token': '3e629af30fce46edaa6ead20e007a276'
}
})
}
}
}])
OR
app.factory('footballData', function($http){
return {
getLeagueData: function(){
return $http({
method: 'GET',
url: 'http://api.football-data.org/v1/competitions/426/leagueTable',
headers:{
'X-Auth-Token': '3e629af30fce46edaa6ead20e007a276'
}
})
}
}
})
Which approach to choose is up to you, there is some docs to assist you on your decision.

Custom URL using Angular ngResource

I would like to know the best practice for connecting with my API as it works as following:
GET -> products/list/latest -> return list of latest products
GET -> products/list/popular -> return list of popular products
GET -> products/list/trending -> return list of trending products
and then when I want a detail of the each product, it is just:
GET -> products/:id
I got the following code in my services.js:
.factory('ProductService', function ($resource) {
return $resource('http://domainname.com/api/products/:product',{product: "#product"});
})
But I really don't know how to access these custom URLs. Can I use the ngResource for that?
Thanks!
Please see here https://docs.angularjs.org/api/ngResource/service/$resource
you can add custom action to ngResources
ie:
var app = angular.module('app', ['ngResource']);
app.factory('ProductService', function($resource) {
var actions = {
'latest': {
method: 'GET',
url: 'api/products/latest '
},
'popular': {
method: 'GET',
url: 'api/products/popular'
},
'trending': {
method: 'GET',
url: 'api/products/trending '
}
};
var ProductService = $resource('/api/products/:productId', {ProductId: '#id'}, actions);
return ProductService;
});
app.controller('MainCtrl', function($scope, ProductService) {
$scope.name = 'World';
ProductService.latest();
ProductService.popular();
ProductService.trending();
ProductService.query();
ProductService.get({id: 1});
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.3/angular.js" data-semver="1.4.3"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-resource.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
</body>
</html>

How to create the cross domain using angularjs?

Hi, I need to create a dropdown list which uses a cross domain to populate it. And i have set a url for it but couldn't find why it is not working .
When the url is in json format it works without any issues but the url is in a xml format. And this is my first work on API's so I will be thank full if anybody help me with this...
---index.html---
<!DOCTYPE html>
<html ng-app="App">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script src="script.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
li span.ng-binding {
color: #f00;
}
</style>
</head>
<body>
<div ng-controller="AppCtrl">
<h1>{{val}}</h1>
<select ng-options="p.ProductName for p in Product"></select>
</div>
</body>
</html>
---script.js---
var App = angular.module('App', [])
.controller('AppCtrl', function($scope, AppFact) {
$scope.val = "Testing the Page For CallsBacks";
AppFact.getData(function(Product) {
$scope.Product = Product;
});
})
.factory('AppFact', function($http) {
return {
getData: function(successcb) {
var url = 'http://xxxxxxxxx';
$http.jsonp(url).
success(function(Product, status, headers, config) {
//alert('ji');
console.warn(Product);
successcb(Product);
}).
error(function(Product, status, headers, config) {
//alert(Product);
//alert("Status is " + status);
});
}
};
});
And Here is my plunker:http://plnkr.co/edit/qq8sELDdZZB5QKe1Pj3T?p=preview
Plz guide me with this because i'm new to API's side..

How to update controller variable with 'ng-model' AngularJS?

I am trying to get user input through a text box using ng-model, and append to a base URL for a http.get call as follow;
index.html:
<html ng-app='vidRoute'>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search Video</title>
<link rel="stylesheet" href="app/css/custom/main.css">
<link rel="stylesheet" href="app/css/custom/responsive.css">
</head>
<body>
<div id='mainwrapper'>
<div id='header' ng-controller="searchController">
<input type="text" id="searchTxt" ng-model="append">
Search Video
</div>
<div id="poster">
<div ng-view></div>
</div>
</div>
<script type="text/javascript" src="app/javascript/vendor/jquery-2.1.1.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-route.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-resource.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-mocks.js"></script>
<script type="text/javascript" src="app/javascript/custom/searchcontroller.js"></script>
<script type="text/javascript" src="app/javascript/custom/vidRoute.js"></script>
</body>
</html>
searchcontroller.js
'use strict';
var vidcontrol = angular.module("vidcontrol", []);
vidcontrol.controller("vidcontroller", ['$scope', '$http', function($scope, $http) {
$http.get('http://api.themoviedb.org/3/tv/airing_today?api_key=d5e87524383e2872a9555990b268dc5b').success(function(response) {
$scope.results = response.results;
});
}]);
vidcontrol.controller('searchController', ['$scope', '$http',
function ($scope, $http) {
var url = "http://api.themoviedb.org/3/search/movie?api_key=d5e87524383e2872a9555990b268dc5b&query=";
// var searchTxt = $('#searchTxt').val();// this works fine when used
var searchUrl = url + append; //$scope.append also logs 'undefined' on the console
$http.get(searchUrl).success(function (response) {
$scope.searchResults = response.results;
});
}]);
but I'm not getting any response. when I log searchUrl on console, I could see that append was not updated according to value from text box. I'm quite new to Angular and I can't figure out what I'm doing wrong. What should I do to fix this?
Now, I see the issue. When controller loaded, it executes controller code. That mean REST query runs before view is built. That is reason you see undefined problem. Solution is to define a method in controller which will be invoked when you click "Search Video".
Update view
Search Video //Look at ng-click
Update Controller:
vidcontrol.controller('searchController', ['$scope', '$http',function($scope, $http) {
var url = "http://api.themoviedb.org/3/search/movie?api_key=d5e87524383e2872a9555990b268dc5b&query=";
$scope.search = function(){ // Look at here, Defined a method to invoke on "Search Video" link click
var searchUrl = url + $scope.append;
$http.get(searchUrl).success(function(response) {
$scope.searchResults = response.results;
});
};
} ]);

Angularjs getting data from controller scope to directive scope

I am trying to get data from resource then add it to isolate scope of directive but when i want to print it to screen i get error as undefined current_page here is the script
/**
* Created by yigit on 10.01.2014.
*/
var app = angular.module('kategori', [
'ngResource',
'apiBaseRoute'
]);
app.factory('Data', ['$resource', 'apiBaseRoute', function($resource, config){
return $resource(config.apiBasePath + 'kategori/?page=:page',{page:1},{
query:{
isArray: false,
method: 'GET'
}
});
}]);
app.controller('KategoriListCtrl',['$scope', 'Data', function($scope, Data){
$scope.allData = {data:null};
Data.query({}, function(data){
$scope.kategoriList = {data:data.cat.data};
$scope.allData.data = data.cat;
});
}]);
app.directive('paginate', function(){
return{
scope:{paginatorData: '=paginate'},
link: function(scope){
alert(scope.paginatorData.current_page);
}
}
});
<!DOCTYPE html>
<html ng-app="kategori">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<div class="col-md-6 col-md-offset-3" ng-controller="KategoriListCtrl">
{{allData.current_page}}
<div paginate="allData"></div>
</div>
<script src="js/lib/angular.min.js"></script>
<script src="js/lib/angular-resource.js"></script>
<script src="js/kategori.js"></script>
<script src="js/apiroute.js"></script>
</body>
</html>
I read this article nested scope
But could not solve my problem.
So, the code alerts undefined. How can i solve this?
Can you show your HTML? You'll need to pass the property like this:
<div data-paginate="paginate"></div>

Resources