Trouble making a back end call through Angular service - angularjs

I am newbie learning to make back end calls from my angular app's service, I am making the back end call from the angular's Service.
I am calling the function in the service from the controller.
The rest service I provided is not the actual service I am hitting, for some reasons I cannot disclose it. I am sure that the rest service I have is valid and is working, cause I was able to hit it though the controller, which is a bad way of doing it, so this is the reason i want to change the back end call to the service.
Below is my js file. Any help would be appreciated, please feel free to let me know if I am doing this wrong.
angular.module("myApp",[])
.controller("myCont", ['myService', function($http, myService){
var vm = this;
this.myUrl = "some rest service";
console.log("The controller");
vm.getDataInController = function() {
console.log("The function is called");
myService.getData(vm)
.success(function (custs) {
console.log("The data is obtained");
})
.error(function (error) {
console.log("some error occurred");
});
}
}])
.service('myService', ['$http', function ($http) {
this.getData = function (vm) {
console.log("control is in the service");
console.log(vm.myUrl);
$http({
type: 'GET',
url: vm.myUrl
// data is where we have the JSON returned in the form of OBJECT from the gis
}).then(function successCallback(response) {
console.log("the backend call worked");
}), function errorCallback(response) {
console.log("the backend call worked");
}
};
}])
;
My Html file is
<!DOCTYPE html>
<html >
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src = "angular-min.js"></script>
<script src = "sampleOneScript.js"></script>
</head>
<body ng-app = "myApp" ng-controller = "myCont as main">
{{main.myUrl}}
<br>
<button type = "button" ng-click = main.getDataInController()>Click me </button>
</body>
</html>
The error I got in the console.
TypeError: Cannot read property 'getData' of undefined
at vm.getDataInController (http://localhost:63342/exercise.weokspce/ng-repeat%20example/sampleOneScript.js:15:26)
at fn (eval at (http://localhost:63342/exercise.weokspce/ng-repeat%20example/angular-min.js:212:87), :4:275)
at f (http://localhost:63342/exercise.weokspce/ng-repeat%20example/angular-min.js:252:82)
at m.$eval (http://localhost:63342/exercise.weokspce/ng-repeat%20example/angular-min.js:132:366)
at m.$apply (http://localhost:63342/exercise.weokspce/ng-repeat%20example/angular-min.js:133:60)
at HTMLButtonElement. (http://localhost:63342/exercise.weokspce/ng-repeat%20example/angular-min.js:252:134)
at HTMLButtonElement.Hf.c (http://localhost:63342/exercise.weokspce/ng-repeat%20example/angular-min.js:35:137)

The problem may be that you are not injecting properly all the dependencies for "myCont". Try changing the line:
.controller("myCont", ['myService', function($http, myService){
with:
.controller("myCont", ['$http', 'myService', function($http, myService){
and see if that corrects things

Related

Angular Service returning "undefined"

So I am sure I am not using best practices, but, I'm just trying to get this to work. I'm making a note taking app, and for whatever reason, the service I created, returns undefined and I can't figure out why.
Here's the service:
angular.module('notesService', []).factory('Notes', ['$http', function($http){
return {
get : function(){
var notes = $http.get('/api/notes');
return notes;
}
}
}]);
And here is the controller:
angular.module('mainController', [])
.controller('mainController', function($scope, Notes){
console.log(Notes.get());
});
The controller is not producing anything on the page just yet, i'm still testing.
Here is what the service returns to my controller:
e {
$$state : {
status : 1,
value : {
config : Object,
data: Array[10]
}
}
}
This isn't the entire thing, but it is all the stuff I need for my purposes.
Whenever I access $$state.value it returns undefined and I have no idea why.
You have the service in an entirely different module. So you gotta inject notesService into angular.module('mainController', [notesService]).
You dont ideally need to add new module for each controller and services, you can have single module and add everything to it
$http return a promise see documentation for $http
Also there is no need of the empty array in the angular.module parameter [] this might be what causes the error see in console.
angular.module('notesService').factory('Notes', ['$http', function($http){
return {
get : function(){
return $http.get('/api/notes');
}
}
}]);
angular.module('mainController')
.controller('mainController', function($scope, Notes){
Notes.get().then(function(result){
console.log(result);
})
});
I created an application that will help you to learn the best practices, plus solve your current problem.
//--In app.module.js--//
angular.module('notesApp', []);
//-- In app.controller.js--//
angular.module('notesApp')
.controller('MainController', ['$scope', '$http', '$log', 'notesFactory',
function($scope, $http, $log, notesFactory) {
$scope.data = {};
notesFactory.getData('http://localhost:3000/api/notes', 'GET')
.then(function(response) {
$log.log(response.data);
}, function(error) {
$scope.data = error;
});
}
]);
//--In app.service.js --//
angular.module('notesApp')
.factory('notesFactory', ['$http',
function($http) {
var notesService = {};
notesService.getData = function(url, method) {
return $http({
url: url,
method: method
});
}
return notesService;
}
]);
<html ng-app='notesApp'>
<head>
<title>
Notes Application
</title>
</head>
<body>
<div ng-controller='MainController'>
<pre>{{ data | json}}</pre>
</div>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js'></script>
<script src='app.module.js'></script>
<script src='app.controller.js'></script>
<script src='app.service.js'></script>
</body>
</html>
Check the console for the json object as shown in the screenshot

angularjs change rootscope after promise in a controller

I'm trying to change some $rootscope variables from within a controller after a I have received a promise from a service.
The $rootscope variables are used to set the html page title attribute etc.
Below is the code I have, I created a function called changeRootPageNotFound() to change the $rootscope variables. It does not work if it's called in the promise.then function.
app.controller('mainController', ['$routeParams', '$scope', '$rootScope', 'mainService', function ($routeParams, $scope, $rootScope, mainService) {
var mainCtrl = this;
mainCtrl.id = $routeParams.itemId;
var promise = mainService.getData($routeParams.id);
promise.then(function (response)
{
if (response.data.data) {
mainCtrl.data = response.data.data;
} else {
mainCtrl.data = false;
changeRootPageNotFound();
}
});
function changeRootPageNotFound() {
$rootScope.title = "Page Not Found - 404";
$rootScope.titleSuffix = "";
}
// changeRootPageNotFound(); // works here
}]);
How can I change the $rootscope variables after I have received the deferred promise from the service?
Add a .catch method:
promise.then(function (response)
{
//if (response.data.data) {
mainCtrl.data = response.data.data;
//} else {
// mainCtrl.data = false;
// changeRootPageNotFound();
//}
}).catch(function(errorResponse) {
console.log(errorResponse.status);
mainCtrl.data = false;
changeRootPageNotFound();
throw errorResponse;
});
The $http service rejects the promise when the status is outside the range 200-299.
What is the throw errorResponse; for, can it be left out?
If the throw errorResponse is omitted, the rejection handler returns a value of undefined. This will convert the rejected promise to a fulfilled promise that resolves as undefined. If there is no further chaining, it can be left out.
A common cause of problems is programmers being unaware of this and unintentionally converting promises.
instead of .catch you can pass the same function to then as the 2nd argument
One of the subtle differences between .catch and using the 2nd argument of the .then method, is that runtime errors in the .then success handler will not be caught in the rejection handler of the 2nd argument.
According to your snippet your code should have worked. In my plunker its working after the deferred promise also.
// Code goes here
angular.module('Test',[])
.service('Service', function($q){
this.ts = function(){
var deferred = $q.defer();
deferred.resolve("hello")
return deferred.promise;
}
})
.controller('Controller', function(Service, $rootScope){
Service.ts().then(function(response){
$rootScope.title="hello";
changeRootPageNotFound();
});
function changeRootPageNotFound() {
$rootScope.title = "Page Not Found - 404";
$rootScope.titleSuffix = "";
}
});
Here is the html
<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs#1.5.8" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="Test">
<div ng-controller="Controller">
<h1>{{title}}</h1>
</div>
</body>
</html>
Please check this Plunker https://plnkr.co/edit/THXDYrWuTqR8UYSJlerB?p=preview

Angular $resource success callback response value?

I am trying to use the $resource for REST API interaction with following code:
Inside Factory:
api.user = $resource(api.baseUrl + '/admin/login', {}, {
login: {method:'POST'}
});
Controller One:
vm.user.$login().$promise.then(function(successResult) {
console.log(successResult);
}, function(errorResult) {
console.log(errorResult);
if(errorResult.status === 404) {
}
});
I get the error : "TypeError: Cannot read property 'then' of undefined" as the $promise is undefined for the resource object.
Question 1: I read on multiple questions that one can use the $promise
property to write the callbacks. What am I doing wrong here that the
$promise property is coming as undefined for login method on user object.
Controller Two:
vm.user.$login(function(successResult) {
console.log(successResult);
}, function(errorResult) {
console.log(errorResult);
if(errorResult.status === 404) {
}
});
This properly processes the success/error handling, however on the successResult object, there are two additional properties of $promise:undefined, $resolved: true, while I was assuming successResponse should be the actual plain object returned by the server, but it looks like an instance of $resource.
Q2: Is there a way to capture the plain object returned by the server
while using the $resource, not having $resource properties?
Any help to resolve the confusion is appreciated.
You can simply call your factory method this way: vm.user.login().$promise.then(function(data) {...
Also you need to use return, as the following: return $resource(api.baseUrl + '/admin/login', {}, {...
I made a snippet, check it:
(function() {
"use strict";
angular.module('app', ['ngResource'])
.controller('mainCtrl', function(userFactory) {
var vm = this;
vm.data = {};
vm.login = function() {
userFactory.login().$promise.then(function(data) {
vm.data = data.status;
}, function(data) {
console.log(data);
});
}
})
.factory('userFactory', function($http, $resource) {
return $resource('http://api.geonames.org/citiesJSON?', {}, {
login: {
method: 'POST'
}
});
})
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular-resource.min.js"></script>
</head>
<body ng-controller="mainCtrl as main">
Response: <pre ng-bind="main.data | json"></pre>
<hr>
<button type="button" ng-click="main.login()">Login</button>
</body>
</html>

How to make an external call to a rest service in another domain [duplicate]

Im trying to get data in a Json format from a remote WS using Angular and im having some trouble.
The data comes from the web service correctly but i cant use it inside the controller.
Why is that?
Angular Code:
var booksJson;
var app = angular.module('booksInventoryApp',[]);
// get data from the WS
app.run(function ($http) {
$http.get("https://SOME_API_PATH").success(function (data) {
booksJson = data;
console.log(data); //Working
});
});
app.controller('booksCtrl', function ($scope) {
$scope.data = booksJson;
console.log($scope.data); //NOT WORKING
});
HTML:
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data">{{book.name}}</h2>
</section>
You should put your $http.get inside your controller.
Also, the web service returns an object not an array. So your ng-repeat should be something like this: book in data.books
Here is a working example:
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks")
.then(function(response) {
$scope.data = response.data;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data.books">{{book.name}}</h2>
</section>
</article>
Create the bookJSON as array, and push the elements instead of assignment. So
var bookJSON=[];
Inside $http.get do
data.forEach(function(item) { bookJSON.push(item); });
The second console log will show undefined because, the call is async. The assignment happens in future.
The run method does not guarantee, that the code is run before controller loads.
There are other ways too to solve this issue.
Avoid global variable. Look at $routeProvider resolve property.
Or implement a service to get this data as promise.
Instead of using a run block you can use your $http service inside the controller, then attach your data to the scope like normal. Just remember to inject the $http service into your controller.
app.controller('booksCtrl', function ($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks").success(function (data) {
$scope.booksJson = data;
});
});
<!DOCTYPE html>
<html>
<head>
<title>test your webservice</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
</section>
</article>
<script type="text/javascript">
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
//ResponseInvocationAgentRequestDTO
var jsonObject = {
"id":65,
"idUserSender": 5}
console.log("aaaaaaaaaaaaaaaaaaaa");
$http({
method: 'put',
url: 'yout URI' ,
data: jsonObject
})
.success(function(data,status){
console.log('all is good', data);
})
.error(function(data,status){
console.log('Erreur into url '+data);
});
});
</script>
</body>
</html>

Getting data from a web service with Angular.js

Im trying to get data in a Json format from a remote WS using Angular and im having some trouble.
The data comes from the web service correctly but i cant use it inside the controller.
Why is that?
Angular Code:
var booksJson;
var app = angular.module('booksInventoryApp',[]);
// get data from the WS
app.run(function ($http) {
$http.get("https://SOME_API_PATH").success(function (data) {
booksJson = data;
console.log(data); //Working
});
});
app.controller('booksCtrl', function ($scope) {
$scope.data = booksJson;
console.log($scope.data); //NOT WORKING
});
HTML:
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data">{{book.name}}</h2>
</section>
You should put your $http.get inside your controller.
Also, the web service returns an object not an array. So your ng-repeat should be something like this: book in data.books
Here is a working example:
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks")
.then(function(response) {
$scope.data = response.data;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
<h2 ng-repeat="book in data.books">{{book.name}}</h2>
</section>
</article>
Create the bookJSON as array, and push the elements instead of assignment. So
var bookJSON=[];
Inside $http.get do
data.forEach(function(item) { bookJSON.push(item); });
The second console log will show undefined because, the call is async. The assignment happens in future.
The run method does not guarantee, that the code is run before controller loads.
There are other ways too to solve this issue.
Avoid global variable. Look at $routeProvider resolve property.
Or implement a service to get this data as promise.
Instead of using a run block you can use your $http service inside the controller, then attach your data to the scope like normal. Just remember to inject the $http service into your controller.
app.controller('booksCtrl', function ($scope, $http) {
$http.get("https://whispering-woodland-9020.herokuapp.com/getAllBooks").success(function (data) {
$scope.booksJson = data;
});
});
<!DOCTYPE html>
<html>
<head>
<title>test your webservice</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="booksInventoryApp">
<section ng-controller="booksCtrl">
</section>
</article>
<script type="text/javascript">
var app = angular.module('booksInventoryApp', []);
app.controller('booksCtrl', function($scope, $http) {
//ResponseInvocationAgentRequestDTO
var jsonObject = {
"id":65,
"idUserSender": 5}
console.log("aaaaaaaaaaaaaaaaaaaa");
$http({
method: 'put',
url: 'yout URI' ,
data: jsonObject
})
.success(function(data,status){
console.log('all is good', data);
})
.error(function(data,status){
console.log('Erreur into url '+data);
});
});
</script>
</body>
</html>

Resources