update $scope info from another controller - angularjs

How can i make the testservice factory return the result from the post request?, or make the app, factory update some $scope details thats within the overallcontroller ?
how can i update information within the overallcontroller from another controller?
app.factory('testservice', ['$http', 'auth', function($http, auth) {
var o = {
posts : []
};
o.test = function() {
return $http.post('/poster', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
console.log(Data);
});
};
return o;
}]);
app.controller('overallController', ['$scope', 'posts', 'testservice', 'auth','$interval',
function($scope, posts, testservice, auth, $interval) {
$scope.data = {cash:"12879999",location:"test2",gang:"None","username":"test",
xp: 1290,
health: 100,
wanted: 30,
energy: 90};
var databackground = function() {
console.log("logging...");
var t = testservice.test;
console.log(t);
}
databackground();
$interval(databackground, 30000);
}]);
example html
<div class="main" ng-controller="overallController">
<section class="sides left" style="background:blue; height:100px;">
<ul>
<li ng-hide="isLoggedIn()">Logg inn</li>
</ul>
</section>
<div ng-controller"othercontroller">
// call made from some code here
</div>
</div>

Change your service to
o.test = function() {
return $http.post('/poster', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).then(function(response){
return response.data;
});
};
And in your controller, do call the service, and get the results back in the promise:
testservice.test().then(function(data) {
$scope.data = data;
});
Read more about how to use promises here

You return the promise from your service, you would listen for that to resovle and get hold of your data.
Using $rootScope is heavy handed approach and should be used as a last resort. Services and event are preferable.
var databackground = function() {
console.log("logging...");
testservice.test()
.then(function (res) {
console.log(res.data); //Here is your data
});
}
EDIT: Your service should change slightly also. Firstly .success and .error are deprecated. Use .then and .catch instead.
If you wish to just return data out of your service just do:
o.test = function() {
return $http.post('/poster', null, {
headers: {
Authorization: 'Bearer ' + auth.getToken()
}
});
};
However if you want to transform the data in your service you can but ensure your return it or your controller wont get anything:
o.test = function() {
return $http.post('/poster', null, {
headers: {
Authorization: 'Bearer ' + auth.getToken()
}
})
.then(function (res) {
res.data.test = 'lol';
return res;
})
};

Try referencing $rootScope instead of $scope.
This will allow controllers and factories to interact with each other.

Related

how to pass http data from service to controller in angularjs

var locationListCtrl=function($scope, loc8rData){
$scope.message = "Searching for nearby places";
loc8rData
.success(function(data){$scope.message = data.length > 0 ? "" : "No locations Found";
$scope.data = { locations: data };
})
.error(function(e){
$scope.message = "Sorry, Something has gone wrong";
console.log(e);
});
};
var loc8rData = function ($http){
return $http.get('/api/locations?lng=33.7741195&lat=-13.9626121&maxDistance=20');
};
Some points:
take into consideration, when you received one response from $http it's the common response (with status, headers, etc). So, if you want to access your data you will have to do: response.data
Usually, when you have a service, you define multiple endpoints. So, you can return an object with multiple requests.
Check this little sample working: https://plnkr.co/edit/FNxEeVZti6D1wmLe
.service('PokeApi', function($http) {
return ({
getPokemon: function (name) {
return $http({
method: 'GET',
url: 'https://pokeapi.co/api/v2/pokemon/' + name,
headers: { 'Content-Type': 'application/json' }
});
}
})
})
And the controller is as simple as:
.controller('MainCtrl', function($scope, PokeApi) {
$scope.name = 'Plunker';
PokeApi.getPokemon('pikachu').then(function (response) {
$scope.pokemon = response.data;
});
});

Passing variable from success call in service through controller to view

In my ui-bootstrap modal I have 3 modal-body div's.
<div class="modal-body" ng-show="$ctrl.selected.item == 'registration'">...</div>
<div class="modal-body" ng-show="$ctrl.selected.item == 'thanks'">...</div>
<div class="modal-body" ng-show="$ctrl.selected.item == 'error'">...</div>
By changing $ctrl.selected.item I change HTML inside my modal window. Now I need to change this variable(property of object indeed) inside a registerService which is injected do registerwindow' controller.
app.service('registerService', ['$http', 'localStorageService', function ($http, localStorageService) {
this.registerUser = function (registerInfo) {
$http({
url: 'http://localhost:3000/v1/sign_up',
headers: {
'Content-Type' : 'application/json'
},
method: 'POST',
data: {
email: registerInfo.email,
nick: registerInfo.nick,
password: registerInfo.password,
password_confirmation: registerInfo.password_confirmation
}
})
.then(function successCall(response) {
console.log('user added'); // delete it
$ctrl.selected.item = $ctrl.items[1];
}, function errorCall(respone) {
console.log('error callback register ');
console.log(respone.data);
$ctrl.selected.item = $ctrl.items[2];
})
};
}]);
This approach with $ctrl.selected.item = $ctrl.items[1]; doesn't work obviously.. How can I do this? I have no clue I need to do this asynchronously.
You could probably use Angular's $q service to handle this. The service's method would look like this:
this.registerUser = function (registerInfo) {
var deferred = $q.defer();
$http({
url: 'http://localhost:3000/v1/sign_up',
headers: {
'Content-Type' : 'application/json'
},
method: 'POST',
data: {
email: registerInfo.email,
nick: registerInfo.nick,
password: registerInfo.password,
password_confirmation: registerInfo.password_confirmation
}
})
.then(function successCall(response) {
console.log('user added'); // delete it
//$ctrl.selected.item = $ctrl.items[1];
deferred.resolve(); //Resolve the promise - success
}, function errorCall(respone) {
console.log('error callback register ');
console.log(respone.data);
//$ctrl.selected.item = $ctrl.items[2];
deferred.reject(); //Reject the promise - failure
});
return deferred.promise;
};
Remember to inject $q into your service!
Within your controller, you'd call your service method like so, then adjust the scope variable within the .then and .catch:
registerService.registerUser(registerInfo)
.then(function() {
$scope.selected.item = $scope.items[1];
//Not sure what your controller looks like, you may be using controllerAs, so this will be a bit different
})
.catch(function() {
$scope.selected.item = $scope.items[2];
});

'Can not read property then' error when using service

I am calling a json in controller using service but I am receiving an error saying "TypeError: Cannot read property 'then' of undefined". I tried existing answers but couldn't get it to work.
Controller:
app.controller("myController",["$scope","MyService","$http", function($scope,MyService,$http){
$scope.hi = "hello";
MyService.getMyData().then(function(response){
console.log(response);
});
}]);
Service:
app.service("MyService", ["$http", function($http) {
this.getMyData = function() {
return
$http({
method: 'GET',
url: 'myList.json',
headers: {
'Content-Type': 'application/json'
}
}).then(function successCallback(response) {
console.log(response);
return response;
}, function errorCallback(response) {
console.log(error);
return response;
});
};
}]);
Thank you.
Currently you had just return(on first line) thereafter on next line you returned $http promise. Basically you have return alone it returns nothing/undefined (this is how javascript works) & next statements are getting ignored from this.getMyData function.
You have to have return & $http({ promise to be together in one line, otherwise return will return empty statement.
this.getMyData = function() {
//`return` & `$http` promise should be on same line, otherwise undefined would get return
return $http({
method: 'GET',
url: 'myList.json',
headers: {
'Content-Type': 'application/json'
}
}).then(function successCallback(response) {
console.log(response);
return response;
}, function errorCallback(response) {
console.log(error);
return response;
});
};
#pankajparker is absolutely correct.
Implemented a codepen for kicks and adjusted to use Angular 1.5's components. Here's the link:
http://codepen.io/Lethargicgeek/pen/YWryoE
(function() {
angular.module("myApp", []);
angular.module("myApp").component('myCmp', {
controller: ctrlFn,
templateUrl: "myCmp.tpl.html"
});
ctrlFn.$inject = ["myService"];
function ctrlFn(myService) {
var $ctrl = this;
// BINDINGS
$ctrl.hi = "hello";
$ctrl.getData = getData;
$ctrl.data = null;
$ctrl.myService = myService; // Binding so that we can easily see results
// END BINDINGS
// FUNCTION
function getData() {
var returnedPrms = myService.getMyData();
returnedPrms.then(function(response) {
$ctrl.data = response;
});
}
// END FUNCTIONS
}
angular.module("myApp").service("myService", svcFn);
svcFn.$inject = ["$http"];
function svcFn($http) {
var svc = this;
//BINDINGS
svc.getMyData = getMyData;
//END BINDINGS
function getMyData() {
var firstPrms = $http.get("http://codepen.io/anon/pen/LVEwdw.js"); // Random bit of json pulled from internets
var secondPrms = firstPrms.then(function success(response) {
svc.successResp = response;
return response;
}, function error(response) {
svc.errorResp = response;
return response;
});
return secondPrms;
}
}
})(); // end iife
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>
<div ng-app="myApp">
<script type="text/ng-template" id="myCmp.tpl.html">
<div>
<h1>{{$ctrl.hi}}</h1>
<a class="btn btn-primary" ng-click="$ctrl.getData()">
Trigger $Http Call
</a>
<dl class="dl-horizontal">
<dt>$ctrl.data:</dt>
<dd>{{$ctrl.data}}</dd>
<dt>$ctrl.myService.successResp:</dt>
<dd>{{$ctrl.myService.successResp}}</dd>
<dt>ctrl.myService.errorResp:</dt>
<dd>{{ctrl.myService.errorResp}}</dd>
</dl>
</div>
</script>
<my-cmp></my-cmp>
</div>

Cannot set property from angularjs service

I am trying to set value in html page from angularjs controller.
I am getting value from web api in service but I have issue that I am always getting error:
TypeError: Cannot set property 'messageFromServer' of undefined
But I can't figure what am I doing wrong here. What am I missing?
On the html part I have:
<div ng-app="myApp" ng-controller="AngularController">
<p>{{messageFromServer}}</p>
</div>
In the controller I have:
var app = angular.module('myApp', []);
app.controller('AngularController', ['$scope', 'messageService', function ($scope, messageService) {
$scope.messageFromServer = "When I set it here it works!"
messageService.getMessage();
}]);
app.service('messageService', ['$http', function ($http) {
this.getMessage = function ($scope) {
return $http({
method: "GET",
url: "api/GetMessage",
headers: { 'Content-Type': 'application/json' }
}).success(function (data) {
$scope.messageFromServer = data;
console.log(data);
}).error(function (data) {
console.log(data);
})
};
}]);
Basically the problem is, you missed to $scope object to the service getMessage method. But this is not a good approach to go with. As service is singleton object, it shouldn't manipulate scope directly by passing $scope to it. Rather than make it as generic as possible and do return data from there.
Instead return promise/data from a service and then assign data to the scope from the controller .then function.
app.service('messageService', ['$http', function ($http) {
this.getMessage = function () {
return $http({
method: "GET",
url: "api/GetMessage",
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
//you could have do some data validation here
//on the basis of that data could be returned to the consumer method
//consumer method will have access only to the data of the request
//other information about request is hidden to consumer method like headers, status, etc.
console.log(response.data);
return response.data;
}, function (error) {
return error;
})
};
}]);
Controller
app.controller('AngularController', ['$scope', 'messageService',
function ($scope, messageService) {
$scope.messageFromServer = "When I set it here it works!"
messageService.getMessage().then(function(data){
$scope.messageFromServer = data;
});
}
]);
Don't use $scope in your service, just return the promise from $http.
var app = angular.module('myApp', []);
app.service('messageService', ['$http', function ($http) {
this.getMessage = function () {
return $http({
method: "GET",
url: "api/GetMessage",
headers: { 'Content-Type': 'application/json' }
});
};
}]);
app.controller('AngularController', ['$scope', 'messageService', function ($scope, messageService) {
messageService.getMessage().then(function(data) {
$scope.messageFromServer = data;
});
}]);
In this example you can unwrap the promise in your controller, or even better you can use the router to resolve the promise and have it injected into your controller.
app.config(function($routeProvider) {
$routeProvider.when('/',{
controller: 'AngularController',
templateUrl: 'views/view.html',
resolve: {
message: function(messageService) {
return messageService.getMessage();
}
}
});
});
Then in your AngularController, you'll have an unwrapped promise:
app.controller('AngularController', ['$scope', 'message', function ($scope, message) {
$scope.messageFromServer = message;
}]);

How to get the data for my controller when http request in progress?

I have following controller
1) introCtrl
2) ArticleCtrl
3) articleService (Service)
Now I am sending an http request from introCrtl
.controller('IntroCtrl', function($scope, articleService) {
articleService.getArticles();
});
and AricleCtrl is
.controller('ArticleCtrl', function($scope,$rootScope,articleService) {
$scope.articles = articleService.fetchArticles();
})
and my Service is
.service('articleService', function ($http, $q) {
var articleList = [];
var getArticles = function() {
$http({
url: "muylink,co,",
data: { starLimit: 0, endLimit: 150,created_date: 0 },
method: 'POST',
withCredentials: true,
}).success(function (data, status, headers, config) {
articleList.push(data);
}).error(function (err) {
console.log(err);
})
};
var fetchArticles = function() {
return articleList[0];
}
return {
getArticles: getArticles,
fetchArticles: fetchArticles
};
});
Which is also working fine. Now Problem is that
Sometimes my http request sending respone late and i got nothing in
$scope.articles.
Can we implement watch here. How i need to implement $watch here. I dont want to implement promise. because i want to run http request behind the scene.
Thanks
It would be better if you switch to a state based setup with ui-router that way you can do this :
$stateProvider.state('myState', {
url: 'the/url/you/want',
resolve:{
articleService: 'articleService' // you are dependency injecting it here,
articles: function (articleService) {
return articleService.getArticles.$promise;
}
},
controller: 'IntroCtrl'
})
// then your controller can just inject the articles and they will be resolved before your controller loads so you it will always be fetched prior
.controller('IntroCtrl', function($scope, articles) {
$scope.articles = articles;
});
for more information take a look at this
ui-router info
All to do is set watch on articleList and provide maintaining function.
As you are watching array, it's good to change it to string.
Create function in watch which results array.
$scope.$watch( function() {
return JSON.stringify($scope.articleList);
}, function(newVal,oldVal){
//provide logic here
});
If your service result is asynchron (like http requests) you should return promises from your service.
.controller('ArticleCtrl', function($scope,$rootScope,articleService) {
articleService.fetchArticles().then(function(articles) {
$scope.articles = articles;
});
})
Service
// not sure about your service logic... simplified:
.service('articleService', function ($http, $q) {
var articleListPromise ;
var getArticles = function() {
articleListPromise = $http(/* ...*/);
};
var fetchArticles = function() {
return articleListPromise.then(function(data) {
return data[0];
});
}
return {
getArticles: getArticles,
fetchArticles: fetchArticles
};
});

Resources