angular js : controller and service - angularjs

I have one service method items.getItems();
getItems: function(callback){
$http({
url: url,
method: "POST"
}).success(function(data, status){
callback(data);
}
}).error(function(err){
console.error('Error: %s error: %O', 'getLanguages[*] failed.', err);
});
}
I use it in my controller, I would like to call it inside the function:
$scope.param= function(){
items.getItems(function(data){
$scope.selectedItemsUpdate = data;
});
return $scope.selectedItemsUpdate}
and in my html page to do like something :
<div data-dy-item data-items="param()"
</div>
But it doens't work

The call is asynchronous. When the service method returns, the callback has not been called yet. So the controller function will always return undefined (or the previous value of selectedItemsUpdate). The AJAX response needs to come back for the callback to be called. So the code should be:
$scope.param = function(){
items.getItems(function(data) {
$scope.selectedItemsUpdate = data;
});
}
And the HTML should be
<div data-dy-item data-items="selectedItemsUpdate"></div>
Of course, the params() function must be called at some time. It should probably be called when the controller is instantiated, or when some button is clicked.

Related

Using the service data in the controller

I have placed the service and the controller in the same js file. So Im trying to fetch the data from the service and use it in my html. In my code Im able to generate the data from the service but not able to assign it to a $scope in the controller and use it in the html. So how do I get the data and assign it to the $scope so that I can use it in my html.
var app = angular.module("app",[]);
app.factory('factoryServices',function($http){
var newObject = {};
var _getChart= function(){
$http.get("http://citibikenyc.com/stations/json")
.success(function(data, status){
if(data) {
return data;
}
}).error(function(data,status){
return error;
});
}
newObject.getChart = _getChart;
return newObject;
});
app.controller("chartController",function($scope,$http,factoryServices){
factoryServices.getChart($scope.chartServicesCompleted);
$scope.chartServicesCompleted = function(data){
$scope.serviceResponse = data;
}
})
If you rewrite your code like this, it should work as expected:
var app = angular.module("app",[]);
app.factory('factoryServices',function($http){
var newObject = {};
var _getChart= function(){
return $http.get("http://citibikenyc.com/stations/json")
.then(function(response){
if(response.data) {
return response.data;
}
}, function(response){
console.error("getChart failed with ",response);
});
}
newObject.getChart = _getChart;
return newObject;
});
and your controller
app.controller("chartController",function($scope,$http,factoryServices){
factoryServices.getChart().then(chartServicesCompleted);
function chartServicesCompleted(data){
$scope.serviceResponse = data;
}
})
The reason your initial code doesn't work, is because your getChart doesn't actually take an argument. So passing your callback like this: getChart($scope.chartServicesCompleted) doesn't do anything. In the rewritten code, I've made it so the getChart function returns the promise created by $http.get(..) which then allows you to use .then([callback]) in your controller.
you are passing a callback function but not handling inside the service method.
do change as
var _getChart= function(callback){
$http.get("http://citibikenyc.com/stations/json")
.success(function(data, status){
callback(data);
}).error(function(data,status){
callback(data);
});
}
now factoryServices.getChart($scope.chartServicesCompleted); will work
you can make more generic by handling success and error callback separately.
or one more way is to implement the success and error logic inside your controller.
but do not forget to check the function type i.e
if(typeof callback == 'function'){
callback(data);
}
Edit: as per advanced you call implement promises.
if you are using angular version 1.6, the success and error methods have been depreciated.
secondly you can do inside service return the http object
var _getChart= function(){
return $http.get("http://citibikenyc.com/stations/json");
}
and then handle the promise in the controller like
factoryServices.getChart().then(successMethod, error method);
Let the service return the promise to the controller. ex:
var _getChart= function(){
return $http.get("http://citibikenyc.com/stations/json");
}
and in the controller handle the promise. Use 'then' instead
factoryServices.getChart().then(function(response){var theDate = response.data},function(error){});
you can declare methods instead in the controller for handling the success and error
factoryServices.getChart).then(onSuccess,onError);
Don use the .success method and .error method. They dont't behave as other promises. So get used to 'then'
You really don't need to handle errors in the service method.I use angular interceptors in most of the cases. Check em out. But sometimes you need to handle the error in the controller. So its good to get the callback in the controller

AngularJS: How to initialize data through $http before executing other part of the code?

I have below code
$scope.init = function (){
console.log($scope.languageFilePath);
$http.get($scope.languageFilePath) //languageFilePath contain url
.then(function(res){
console.log('scueese');
$scope.translate = res.data;
console.log($scope.translate.SERVICE);
// $scope.eqipment = $scope.translate['COLOR'];
//console.log("Data String "+equip);
//$scope.eqipment="ghsh"
});
};
$scope.init();
Now what is my issue this method calling properly but before initializing $scope.translate its executing other part of code.
What changes i have to do in the code so first its initialize $scope.translate then only it call some other methods of file .
Note:- $http.get() method calling when this method invoked after that other methods are executing and code inside then executing after those method called.
If your problem is to execute the code after $scope.init() invocation, you could try to use the http.get promise, like this:
$scope.init = function (){
console.log($scope.languageFilePath);
return $http.get($scope.languageFilePath) //languageFilePath contain url
.then(function(res){
console.log('scueese');
$scope.translate = res.data;
console.log($scope.translate.SERVICE);
});
};
$scope.init().then(function(){
//this code will be executed after the http get...
});
EDIT 1
after receiving some more code from OP, you should modify your .js file as shown here: http://pastebin.com/mFUWSU0N
this way, ALL the code below init() will be executed after the $http.get completion.
may be you should out the wanted function in your init:
$scope.init = function (){
console.log($scope.languageFilePath);
return $http.get($scope.languageFilePath) //languageFilePath contain url
.then(function(res){
console.log('scueese');
$scope.translate = res.data;
console.log($scope.translate.SERVICE);
myFunc();
myFunc2();
});
};
What you also could do is make it a dependency of your controller.
Lets say for instance you are using the routeprovider to navigate to your page you could then do this:
myApp.config(['$routeProvider',function ($routeProvider) {
$routeProvider.when('../../goto/yourpage', {
templateUrl: '/yourpage.html',
controller: 'myController',
resolve: {
initializeFunction: function($http) {
// do some logic you want executed before anything else
return $http.get("blablabla").$promise;
});
}
}
});
}]);
then in your controller that is active on yourpage.html you can do:
myApp.controller('myController',function ($scope,initializeFunction) {
$scope.possibleReturnFromTheFunction = initializeFunction;
});

Data in callback when using 'Controller as' pattern in Angular

I have the simplest angular controller:
tc.controller('PurchaseCtrl', function () {
var purchase = this;
purchase.heading = 'Premium Features';
this.onSuccess = function (response) {
console.log('Success', response);
lib.alert('success', 'Success: ', 'Loaded list of available products...');
purchase.productList = response;
};
this.onFail = function (response) {
console.log('Failure', response);
};
console.log('google.payments.inapp.getSkuDetails');
lib.alert('info', 'Working: ', 'Retreiving list of available products...');
google.payments.inapp.getSkuDetails(
{
'parameters': {'env': 'prod'},
'success': purchase.onSuccess,
'failure': purchase.onFail
});
});
And the view:
<div class="col-md-6 main" ng-controller="PurchaseCtrl as purchase">
{{purchase}}
</div>
This prints out:
{"heading":"Premium Features"}
I thought that when the callback returned, the view would be update with any new data. Am I missing something? The callback returns and I see the dtaa in the console.
Using the $scope pattern I think that I would use $scope.$apply to async method, but I'm not sure how to do that here.
Using controllerAs does not change the way digest cycle works or anything. It is just a sugar that adds a property (with the name same as alias name when used) to the current scope with its value pointing to the controller instance reference. So you would need to manually invoke the digest cycle (using scope.$apply[Asyc]() or even with a dummy $timeout(angular.noop,0) or $q.when() etc) in this case as well. But you can avoid injecting scope by abstracting it out into an angular service and returning a promise from there, i.e
myService.$inject = ['$q'];
function myService($q){
//pass data and use it where needed
this.getSkuDetails = function(data){
//create deferred object
var defer = $q.defer();
//You can even place this the global variable `google` in a
//constant or something an inject it for more clean code and testability.
google.payments.inapp.getSkuDetails({
'parameters': {'env': 'prod'},
'success': function success(response){
defer.resolve(response);// resolve with value
},
'failure': function error(response){
defer.reject(response); //reject with value
}
});
//return promise
return defer.promise;
}
}
//Register service as service
Now inject myService in your controller and consume it as:
myService.getSkuDetails(data).then(function(response){
purchase.productList = response;
}).catch(function(error){
//handle Error
});

Variable does not pass to the view from the controller

I am new in AngularJs and can not figure out with such problem.
I try to change the variable in the scope that unassuming way.
.controller('AuthController', function($scope,Auth) {
$scope.submit = function() {
Auth.login($scope.username,$scope.password, function(result){
$scope.result = result
});
}
})
Where Auth is a service which makes GET request to server and gets response like this:
{ 'status': 1, 'message': "User does not found!"}
But my variable does not refresh in my template. When I put this
$scope.result = { 'status': 1, 'message': "User does not found!"}
outside the function $scope.submit. It works fine.
This is my routing.
$stateProvider
.state('index', {
url: "/",
templateUrl: "/static/templates/_index.html",
})
My template is.
<div class="alert" >{{ result.message }}</div>
Can someone explaine me what do I do wrong?
Thanks.
This is my service.
function login(username, password, callback) {
return $http.post('/api/login/', {
username: username, password: password
}).success(callback);
}
After inserting
Auth.login($scope.username,$scope.password, function(result){
$scope.result = result
console.log($scope.result);
I see correct data in my firebug.
Object { status=1, message="User does not found!"}
$scope.$apply(); - gives me Error: [$rootScope:inprog] http://errors.angularjs.org/1.4.0/$rootScope/inprog?p0=%24digest
Are you sure Auth.login() doesn't return a promise. It looks like it wants to, in which case try...
Auth.login($scope.username, $scope.password)
.then(function(result){
$scope.result = result
});
Hard to say without seeing your Auth service.
If your Auth.login() returns a promise you can use its then function to define success and error handler e.g:
Auth.login($scope.username, $scope.password)
.then(function(result){// success handler
$scope.result = result
$scope.$apply();
},function(error){// error handler
console.log(error);
});
However if it makes an ajax call and does not return a promise, you can use $q service to return a promise by yourself. Here's how you can do it:
var deferred = $.defer();
deferred.resolve($.ajax({
// Your ajax call
}));
You can return promise using return deferred.promise.
Note : Make sure you inject $q service in your Auth service.
The problem was decided by changing
$scope.result = result.data;
on
$scope.blabla = result.data;
And after that magic my template finally show me {{ blabla }} variable.
Angular dose not live up my expectation :-(

Angular Editable Field Reverting to Original Name After Change

I am trying to remotely get a user's name and then have it editable so that it can be saved again. I am getting the name correctly, but when I try to change it, it reverts back to the old name.
Am I doing something wrong with the defer and resolve?
var deferred = $q.defer();
$http({
url : '/getuser',
method : 'GET',
}).success(function(data) {
deferred.resolve(data);
});
return deferred.promise;
http://jsfiddle.net/NfPcH/181/
You're assigning the promise directly to your model variable. So even though in many ways your variable acts like it got the results of the promise it actually instead contains a binding to the promise.
So your variable keeps getting set to resolved value of the promise during $digest cycles - overwriting your edits.
So instead of binding your variable to the promise like this:
$scope.myUser = getUser();
Use the promise's then method and assign the results of the promise. This way myUser is initialized to the results of your promise just once instead of being perpetually bound to the promise itself.
getUser().then(function(result) {
$scope.myUser = result;
});
For this example, you don't really need to have an explicit promise. $http already returns a promise so you really don't need to define a new one.
I've re-arranged the code a bit. In order to initialize the value, I'm using ng-init to call the getUser() method. This then calls $http and binds to the $scope.myUser. BTW, I noticed that in only ever enters the error callback.
Because promises are async, you must bind to the $scope inside the success or error callback function of $http.
The reason it was reverting to the 'old' value was because you were binding directly to the function getUser(). This meant that angular was setting up a $watch on the return value of this function.
Here is a working fiddle.
HTML:
<h4>remote</h4>
<div ng-app="app" ng-controller="Ctrl" ng-init="init()">
<a href="#" editable-text="myUser.name" >
{{ myUser.name || 'not set!' }}
</a>
</div>
JS:
app.controller('Ctrl', function($scope, $http, $q) {
$scope.myUser = null;
$scope.init = function() {
getUser();
};
function getUser() {
return $http({
url : 'http://espn.com/images/test-data/public-profile.json',
method : 'GET',
})
.error(function(data) {
$scope.myUser = {"name":"bobby","age":"21"};
})
.success(function(data) {
console.log(data);
$scope.myUser = data;
});
};
});

Resources