Make part of $http.get URL dynamically generate - angularjs

I'm pulling in an array from an API, like so:
// in Service....
return $http.get(
'http://api.com/team/16110?Authorization=565eaa22251f932b9f000001d50aaf0b55c7477c5ffcdbaf113ebbda'
)
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
This works fine, but only for the one array of data that the URL calls. I want to be able to call in other specific arrays by adapting one part of the URL - 16110.
I want to be able to use a property from a separate property elsewhere within this $http call. I tried this:
'http://api.com/team/' + $scope.thisId +'?Authorization=565eaa22251f932b9f000001d50aaf0b55c7477c5ffcdbaf113ebbda'
But this just broke the Service.
Is there a relatively simple solution to this? I feel like I'm really close, but can't crack it.
UPDATE - the following solution works...
1. SERVICE
app.factory('DataService', ['$http', function($http) {
return {
getTeamDetailsById: function(teamId) {
return $http.get('http://api.com/team/' + teamId + '?Authorization=xxxxxx'
)
}
}]);
2. CONTROLLER
app.controller('NationsController', [
'$scope',
'DataService',
NationsController]);
function NationsController($scope, DataService) {
self = this;
DataService.getTeamDetailsById($scope.whichTeam).then(
function(response) {
//success callback
$scope.teamDetails = response.data;
},
function(response) {
//an error has occurred
});
}
3. response.data
I am expecting to get back an object from this. The API URL is fine, I've tried it directly and it returns the data ok.

Pass the id from the scope into the service:
app.factory("DataService", ["$http", function($http) {
return {
getTeamDetailsById: function(teamId) {
return $http.get('path/to/api' + teamId + '?Auth=xxxx')
}
};
}]);
Call it from the controller:
DataService.getTeamDetailsById($scope.teamId).then(function(response) {
//success callback
$scope.teamDetails = response.data;
}, function(response) {
//an error has occurred
});

This:
'http://api.com/team/' + '$scope.thisId' +'?Authorization=565eaa22251f932b9f000001d50aaf0b55c7477c5ffcdbaf113ebbda'
is equal to http://api.com/team/$scope.thisId?Authorization=[...], which is not what you want. Remove the quotes around $scope.thisID, like this:
'http://api.com/team/' + $scope.thisId +'?Authorization=565eaa22251f932b9f000001d50aaf0b55c7477c5ffcdbaf113ebbda'
This will work assuming you've set $scope.thisId to whatever resource's ID you want to fetch.

Related

How to chain promises returned from Services in AngularJS

According to best practices I have created a service for all different chunks of API call and call the file as api.js;
Here is one example.
api.service('Auth', function(Config, $http, $q, $state) {
this.login = function(jsonToSend) {
return $http.post(Config.apiurl + '/user/auth/login', jsonToSend)
.then(function(response) {
return response.data;
}, function(error) {
return $q.reject(error.data);
});
};
// Api function for signing the user up
this.signup = function(jsonToSend) {
return $http.post(Config.apiurl + '/user/auth/signup', jsonToSend)
.then(function(response) {
return response.data;
}, function(response) {
return $q.reject(response.data);
});
};
});
Now in my loginController.js I inject this service with other services. Now what I want to is.
Auth.Login()
.User.getUser()
.User.getCart()
.Item.getProduct()
My kiddish attempt. I know it's wrong but the community asks you to show what you did.
var q = $q.defer() //intialize
Auth.login().then(function(response){
//some manipulation and store stuff in data
$q.resolve(data);
})
.then(function(data){
})
I want to chain them like this. I know the representation is wrong, but I hope you get the idea of what I am trying to do here.
I have another option of doing this via waterfall method of async.js/ underscore.js but I want to improve my knowledge on promises and hence would like to know if this approach is possible.
Thanks.
You can to save the promises to vars like this:
var loginPromise = Auth.login();
var userPromise = User.getUser();
var chartPromise = User.getCart();
var productPromise = Item.getProduct();
Then you can wait for all promises to resolve and do something with the results like this:
$q.all([loginPromise, userPromise , chartPromise , productPromise]).then(function(data){
/* You can Access each promise data with the index of the order you put them into $q.all(..
* data[0], data[1], data[2], data[3]
*/
});

how to get id using promise from service using controller

hey guys, i have problem with get id. now i cant get '_id' from service.
this is my service
application.service('Arrears', [
function()
{
var db = new PouchDB('localhost:5984/arrears');
return {
get: function (_id) {
return db.get(_id)
.then(function (object) {
return db.remove(object)
.catch(function (err) {
console.log('error: ' + err); // isn't executed
});
})
.catch(function (err) {
console.log('error: ' + err); // isn't executed
});
},
}
}
]);
for insert data is ok.
now, this is my controller.
application.controller('ArrearsManagementAllController', ['$location', '$mdSidenav', '$scope', 'Arrears',
function($location, $mdSidenav, $scope, Arrears)
{
$scope.id = Arrears.get();
}
]);
and the last is my template.
<md-list-item
md-virtual-repeat="i in items"
ng-click="read(id)">
when i click read, my link show like this
localhost:8080/arrears_management/all/read/undefined
my code can't read the id.
please solve my problems. because im new using angularjs and pouchdb.
now the console show error like this :-
GET localhost/arrears/_id?_nonce=1447904157421 404 (Object Not Found)
wrong things with your code:
1.
get: function (_id) {
var id = get('_id')
},
does not return anything, and
2. get is calling a get method which is not defined
3. you don't have _id anywhere to return it. Maybe you want to put it in a service variable after you get it from the database?
OR, you probably wanted to do this:
get: function (_id) {
var id = db.get('_id');
return id;
},
note the db.get instead of just get and the very useful return. This may depend on the database engine, though...
EDIT
even in the controller you have a big issue: $scope.id = Arrears.get does a more complicated thing that you wish. You just need to replace it with:
$scope.id = Arrears.get();
in order to get the value of id because you were not calling the get method...

Angular How to properly use a factory returned data

I have a factory use $resource to make HTTP calls.
The factory code:
.factory('me', function($resource, API_URL) {
var url = API_URL + 'api/me';
return $resource(url);
})
I use it in a controller and I manage to display the data returned from factory in view like this:
.controller('AppCtrl', function($scope, me) {
$scope.data = me.get();
console.log($scope.data);
})
View code to display this data was obiously like this:
<h3>{{data.displayName}}</h3>
when I took a look at my console I found that am getting the data but I also getting $promise and $resolved I had a feeling that am not doing it the way it meant to be and I made sure when I tried to use the same factory in different controller like this:
.controller('newItemCtrl', function($scope, me) {
var data = me.get();
console.log(data.displayName);
})
I got undefined.
My question again how it work in the first use and didn't in the second use.
$resource.get() does not immediately return data. Instead it returns an empty reference that is updated with the data once the data is returned from the server.
Instead of directly assigning the result of the get() to your scope variable, you should be using the success and error callbacks:
angular.module('foo').controller('AppCtrl', function($scope, me) {
me.get(function (result) {
$scope.data = result;
console.log($scope.data);
}, function (error) {
// handle error here
});
});
It returns a promise, so you should use like that:
.controller('AppCtrl', function($scope, me) {
$scope.data = me.get(function(data) {
$scope.data = data;
console.log($scope.data);
})
})
https://docs.angularjs.org/api/ngResource/service/$resource

Return value of a promise to a function in AngularJS

I have a problem with outputting the values of a promise function.
$scope.getTeacher = function(teacherAbr) {
var promise = dataService.getTeacher(teacherAbr);
var testje = promise.then(function(payload) {
return payload;
});
return testje; // outputs an d object, not the direct payload values
};
The output of this controller function is this:
However, when I'm doing testje.$$state it returns undefined. How can I output the value object? I can't output the payload variable in a new $scope, because this data is dynamic.
Here is a simplified version of this on Plunker.
You should change the way you think about things when you work with asynchronous code. You no longer return values, instead you use Promise or callback patterns to invoke code when data becomes available.
In your case your factory can be:
.factory('dataService', function($http, $log, $q) {
return {
getTeacher: function(teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two').then(function(response) {
return response.data;
}, function() {
$log.error(msg, code);
})
}
};
});
And usage in controller:
dataService.getTeacher('Lanc').then(function(data) {
$scope.teacher = data;
});
Also $http.get already returns promise, so you don't have to create one more with $q.defer().
Demo: http://plnkr.co/edit/FNYmZg9NJR7GpjgKkWd6?p=preview
UPD
Here is another effort for combining lessons with teachers.
Demo: http://plnkr.co/edit/SXT5QaiZuiQGZe2Z6pb4?p=preview
//in your services file
return {
getTeacher: function (teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two')
})
//change the controller to this
dataService.getTeacher(teacherAbr).then(function(msg){
$scope.getdata=msg.data;
console.log("From server"+msg.data);
});

How to use data from $http in other controller

How can I use the totalResults outside of the function that Im setting it? I just cant wrap my head around how to do it, I need to use the totalResults that I gather from my database and use in another function to calculate the amount of pages. I do this so I dont load all the data to the client but I still need to know the total count of rows in the database table.
My json looks like:
Object {total: 778, animals: Array[20]}
Angular:
var app = angular.module('app', []);
app.controller('AnimalController', ['$scope', 'animalSrc', function($scope, animalSrc)
{
$scope.animals = [];
var skip = 0;
var take = 20;
var totalResults = null;
//$scope.totalResults = null;
$scope.list = function()
{
animalSrc.getAll(skip, take, function(data) {
$scope.animals = $scope.animals.concat(data.animals);
// I need to be able to use this outside of function ($scope.list)
totalResults = data.total;
//$scope.totalResults = data.total;
});
};
$scope.showMore = function()
{
skip += 20;
$scope.list();
};
$scope.hasMore = function()
{
//
};
// Outputs null, should be the total rows from the $http request
console.log(totalResults);
}]);
app.factory('animalSrc', ['$http', function($http)
{
// Private //
return {
getAll: function(skip, take, callback)
{
$http({
method: 'GET',
url: 'url' + skip + '/' + take
}).
success(function(data) {
callback(data);
}).
error(function(data) {
console.log('error: ' + data);
});
}
};
}]);
You need to start thinking asynchronously. Your console.log is called before the $http has returned and totalResults has been set. Therefore, totalResults will always be null.
You need to find some way to delay the call to console.log so that the $http call can finish before you run console.log. One way to do this would be to put the console.log call inside your callback function so that it is definitely called after $http's success.
A more elegant way to do this is to use promises. angular.js implements $q, which is similar to Q, a promise library.
http://docs.angularjs.org/api/ng.$q
Instead of creating a callback function in getAll, you return a promise. Inside $http success, you resolve the promise with the data. Then, in your controller, you have a function that is called when the promise is resolved. Promises are nice because they can be passed around and they allow you to control the flow of your asynchronous code without blocking.
Here's a boilerplate I was just working on for myself for similar setup where data is an object that needs to be split into more than one scope item. Issue you weren't grasping is storing the data within the service, not just using service to retrieve data. Then the data items are available across multple controllers and directives by injecting service
app.run(function(MyDataService){
MyDataService.init();
})
app.factory('MyDataService',function($http,$q){
var myData = {
deferreds:{},
mainDataSchema:['count','items'],
init:function(){
angular.forEach(myData.mainDataSchema,function(val,idx){
/* create deferreds and promises*/
myData.deferreds[val]=$q.defer();
myData[val]= myData.deferreds[val].promise
});
/* load the data*/
myData.loadData();
},
loadData:function(){
$http.get('data.json').success(function(response){
/* create resolves for promises*/
angular.forEach(myData.mainDataSchema,function(val,idx){
myData.deferreds[val].resolve(response[val]);
});
/* TODO -create rejects*/
})
}
}
return myData;
})
app.controller('Ctrl_1', function($scope,MyDataService ) {
$scope.count = MyDataService.count;
$scope.items =MyDataService.items;
});
app.controller('Ctrl_2', function($scope,MyDataService ) {
$scope.items =MyDataService.items;
$scope.count = MyDataService.count;
});
Plunker demo

Resources