Retrieving data from dynamic URL - angular - angularjs

I'm trying to retrieve data with the following code, where the URL of the service has a dynamic parameter ie. the id, there is something wrong because the data isn't displaying, when I load the URL in the browser with this on the end:
../categories/165
could I get some help please? Thanks.
...
.when('/categories/:categoryId', {
controller: 'BookCategoryController',
templateUrl: 'views/booksincategory.html'
})
...
controller
app.controller('BookCategoryController', ['$scope', 'bookcategories', '$routeParams', function($scope, bookcategories, $routeParams) {
bookcategories($scope.id).success(function(data) {
console.log($scope.id);
$scope.detail = data.books[$routeParams.categoryId];
});
}]);
service
app.service('bookcategories', ['$http', function($http) {
return {
get: function(id) {
return $http.get('http://52.41.65.211:8028/api/v1/categories/'+ id + '/books.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}
}
}]);
booksincategory.html
<div class="category col" ng-repeat="book in detail">
<h3 class="title">{{book.title}}</h3>
</div>

Change your service code to :
app.service('bookcategories', ['$http', function($http) {
return {
getAllBooks: function(id) {
return $http.get('http://52.41.65.211:8028/api/v1/categories/'+ id + '/books.json')
}
}
}]);
and in Controller :
bookcategories.getAllBooks($scope.id).then(function(response) {
$scope.detail = response.data.books[$routeParams.categoryId];
});
EDIT2
You have to define $scope.id somewhere in your controller like below :
$scope.id= 1 ;
console.log($routeParams.categoryId);//check what you are getting here
bookcategories.getAllBooks($routeParams.categoryId).then(function(response) {
$scope.detail = response.data.books[$routeParams.categoryId];
});
after this your service URL will go like below (Took this URL from your Question)
http://52.41.65.211:8028/api/v1/categories/1/books.json
See 1 in the URL its $scope.id !

.success & .error function(deprecated since angular 1.4.X) are not chainable-friendly, so it prevents to return a promise object from get method. Removing success & error callback will allow to return promise object from function. Consider using .then function over promise since .success & .error callback deprecated.
get: function(id) {
return $http.get('http://52.41.65.211:8028/api/v1/categories/'+ id + '/books.json');
}
//controller code & pass `$routeParams.categoryId` in it
bookcategories($routeParams.categoryId).then(function(response) {
$scope.detail = response.data.books[$routeParams.categoryId];
});

Related

Angular not loading data from external json

Not sure what I have wrong here in this setup to simply display books in a json,
I think it might be the view or the controller that may be wrong, but I'm unsure. Thanks for any help.
<div class="book col" ng-repeat="book in myBooks">
<h3 class="title">{{book.title}}</h3>
<p class="author">{{book.author}}</p>
</div>
services.js
app.factory('books', ['$http', function($http) {
return $http.get('books.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
books.json
{
"per_page":20,
"page":1,
"total_pages":1468,
"total_results":29346,
"books":[
{
"uuid":"235b68e4-5b16-4a25-b731-45c7e67c351e",
"id":98024,
"title":null,
"author":null,
"language":null,
"createtime":"2016-05-19T13:09:40.963+00:00"
},
{
"uuid":"5e87daca-e87b-4324-a652-e06d5349bd82",
"id":98055,
"title":null,
"author":null,
"language":null,
"createtime":"2016-05-23T15:50:11.777+00:00"
}
Controller.js
app.controller('BookshelfController', ['$scope', 'books', function($scope, books) {
books.success(function(data) {
$scope.myBooks = data;
});
}]);
Return from your factory an object which contains your function, calling which will return you the result of $http.get()
app.factory('books', ['$http', function($http) {
return {
getBooks: function() {
return $http.get('books.json');
}
};
}]);
Because $http.get returns a Promise object, in your controller use then to get the results from the response.
app.controller('BookshelfController', ['$scope', 'books', function($scope, books) {
books.getBooks().then(function (data) {
$scope.myBooks = data;
}, function (err) {
console.log(err);
});
}]);
Also check your url to be correct.

AngularJS: Directive to controller communication: $(http).get(...).success is not a function

I am trying to send data from factory to a controller but I get the following error:
$(http).get(...).success is not a function
Factory code:
app.factory('sportsFactory', ['$http', function($http) {
return $http.get('data/sports.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
Controller code:
app.controller('NavbarController',['$scope', 'sportsFactory',
function($scope, sportsFactory){
sportsFactory.success(function(data){
$scope.sports = data;
});
}]);
If I pass a data without using $http it works!
it is better to create a factory method instead of returning one http request, because that way you can use same factory for several occasions like different http requests for example. But in here this factory only usable for this http request only. So create a function and call that method inside controller.
app.factory('sportsFactory', ['$http', function($http) {
return {
sendReq: function() {
return $http.get('data/sports.json')
}
}
}]);
Note that you don't have to return the success inside the factory since the controller handling the response/promise.
call sendReq method from the controller like this
app.controller('NavbarController', ['$scope', 'sportsFactory',
function($scope, sportsFactory) {
sportsFactory.sendReq().success(function(data) {
$scope.sports = data;
});
}
]);
Note that success is not available since angular 1.6. so beware of your version. if its a latest version use then instead of success like this
app.controller('NavbarController', ['$scope', 'sportsFactory',
function($scope, sportsFactory) {
sportsFactory.sendReq().then(function(response) {
$scope.sports = response.data; // data comes under data property in then
});
}
]);
Change your factory code just return the http promise, and handle it in your controller.
app.factory('sportsFactory', ['$http', function($http) {
return $http.get('data/sports.json')
}]);
If you return a promise from the service, you can handle both success and error callbacks in your controller.
Your controller will be,
app.controller('NavbarController',['$scope', 'sportsFactory',
function($scope, sportsFactory){
sportsFactory.then(function(data) {
$scope.sports = data;
})
.error(function(err) {
console.log(err);
});
}]);
Use, then instead if success since success is deprecated in the latest versions.
app.factory('sportsFactory', ['$http', function($http) {
return $http.get('data/sports.json')
}]);
and in controller
app.controller('NavbarController',['$scope', 'sportsFactory',
function($scope, sportsFactory){
sportsFactory.then(function(data){
$scope.sports = data;
});
}]);

how to reload a partial view on success of a function that is defined in factory

I want to reload a webpage on success of a function. I'd like not to loose the cookie data upon reload too. I don't know how to achieve this as I have defined the function using factory in my controller.
JavaScript Code
'use strict';
angular.module('employees', ['ngTable']);
//Routers
//Factories
myApp.factory('employeeServices', ['$http', function($http) {
var factoryDefinitions = {
moveToBench: function(employeeId) {
return $http.post(myApp.IndecommBaseUrl + '/Workflow?entityId=' + employeeId + '&nextStateId=' + myApp.state.bench)
.success(function(data) {
$route.reload();
});
}
}
return factoryDefinitions;
}]);
//Controllers
myApp.controller('getEmployeesController', ['$scope', 'employeeServices', 'dataTable', function($scope, employeeServices, dataTable) {
employeeServices.getEmployees().then(function(result) {
$scope.data = result.data;
if (!result.data.error) {
dataTable.render($scope, '', "employeesList", result.data);
}
$scope.moveToBench = function(id) {
employeeServices.moveToBench(id);
}
});
}]);
I want the refresh to happen on success of the function 'moveToBench'.
How can I achieve this?
Thanks in advance...
Is the reload not working? Or the factory is not even called? Anyway, This is how I do my reloads:
$window.location.reload();
Give it a try to see if it works =)

Send path from controller to a service which will return a promise back to controller

I have a service which get data from a file(path is given by the controller) and return a promise - then another service that create a object with properties using the returned data from the last service.
My problems are:
The getDataService runs before controller so it has no path from which to fetch data => nothing in return(an error)
Provider 'GetDataService' must return a value from $get factory method.
I need to keep this structure because I'll have more controllers with different paths to give
I'm also opened to other solutions but I need to make sure that datas are loaded before the template get populated. I've tried to call SetProperties service first with getData service into it - but still getData.js is executed first
getdata Service
angular.module('myApp').factory('GetDataService',['$http', function($http) {
var getData = function(path){
return $http.get(path).then(function(result) {
return result.data;
});
};
}]);
setProperties service
angular.module('myApp').service('PageProperties',['$http', function($http) {
this.setProps = function(page, data) {
some code here
var properties = {
isCenterActive : isActive_val,
//header elements
titleClass : page,
title : data.titles[page],
//footer elements
leftLink : leftLink_val,
leftFooterClass: leftLink_val,
leftTitle: data.titles[leftLink_val],
centerLink : centerLink_val,
centerFooterClass: data.titles[centerLink_val],
centerTitle : centerTitle_val,
rightLink : rightLink_val,
rightFooterClass: rightLink_val ,
rightTitle : data.titles[rightLink_val],
}
return properties;
}
}]);
controller
angular.module('myApp', [])
.controller('meniuController', ['$http', '$stateParams', '$scope', 'GetDataService', 'PageProperties',
function($http, $stateParams, $scope, GetDataService, PageProperties){
var page = "meniu";
$scope.language = $stateParams.lang;
var path = '_global/views/services/json/' + $stateParams.lang + '_data.json';
/*PageProperties.setProps(page, path).then(function(data){
//some code here
});*/
GetDataService.getData(path).then(function(data){
$scope.props = PageProperties.setProps(page, data);
}).catch(function(){
$scope.error = 'Unable to get data';
});
}])
Thanks in advance!!
The error says your GetDataService provider (defined as factory) doesn't return anything
angular.module('myApp').factory('GetDataService',['$http', function($http) {
var getData = function(path){
return $http.get(path).then(function(result) {
return result.data;
});
};
// you need to actually return something
return { getData: getData };
}]);
Then you can make your PageProperties use GetDataService
angular
.module('myApp')
.service('PageProperties',['GetDataService', function(GetDataService) {
this.getProperties = function(path) {
return GetDataService.getData(path).then(/*transform here*/)
}

Angular ui-router get asynchronous data with resolve

I want to display a form with data corresponding to the edited item. I use ui-router for routing. I defined a state:
myapp.config(function($stateProvider) {
$stateProvider.
.state('layout.propertyedit', {
url: "/properties/:propertyId",
views : {
"contentView#": {
templateUrl : 'partials/content2.html',
controller: 'PropertyController'
}
}
});
In PropertyController, I want to set $scope.property with data coming from the following call (Google Cloud Endpoints):
gapi.client.realestate.get(propertyId).execute(function(resp) {
console.log(resp);
});
I don't know if I can use resolve because the data are returned asynchronously. I tried
resolve: {
propertyData: function() {
return gapi.client.realestate.get(propertyId).execute(function(resp) {
console.log(resp);
});
}
}
First issue, the propertyId is undefined. How do you get the propertyId from the url: "/properties/:propertyId"?
Basically I want to set $scope.property in PropertyController to the resp object returned by the async call.
EDIT:
myapp.controller('PropertyController', function($scope, , $stateParams, $q) {
$scope.property = {};
$scope.create = function(property) {
}
$scope.update = function(property) {
}
function loadData() {
var deferred = $q.defer();
gapi.client.realestate.get({'id': '11'}).execute(function(resp) {
deferred.resolve(resp);
});
$scope.property = deferred.promise;
}
});
You need to read the docs for resolve. Resolve functions are injectable, and you can use $stateParams to get the correct value from your routes, like so:
resolve: {
propertyData: function($stateParams, $q) {
// The gapi.client.realestate object should really be wrapped in an
// injectable service for testability...
var deferred = $q.defer();
gapi.client.realestate.get($stateParams.propertyId).execute(function(r) {
deferred.resolve(r);
});
return deferred.promise;
}
}
Finally, the values for resolve functions are injectable in your controller once resolved:
myapp.controller('PropertyController', function($scope, propertyData) {
$scope.property = propertyData;
});
I think your controller function needs $stateParams parameter from which you can get your propertyId. Then you can use $q parameter and create promise to set $scope.property with something like this:
var deferred = $q.defer();
gapi.client.realestate.get(propertyId).execute(function(resp) {
deferred.resolve(resp);
});
$scope.property=deferred.promise;
Here is description of using promises for handling async calls.
Try this easy way to use resolve in proper way
State code:
.state('yourstate', {
url: '/demo/action/:id',
templateUrl: './view/demo.html',
resolve:{
actionData: function(actionData, $q, $stateParams, $http){
return actionData.actionDataJson($stateParams.id);
}
},
controller: "DemoController",
controllerAs : "DemoCtrl"
})
In the above code I am sending parameter data which I am sending in the url,For examples if i send like this /demo/action/5
this number 5 will go to actionData service that service retrieve some json data based on id.Finally that data will store into actionData You can use that in your controller directly by using that name
Following code return some JSON data based on id which iam passing at state level
(function retriveDemoJsonData(){
angular.module('yourModuleName').factory('actionData', function ($q, $http) {
var data={};
data.actionDataJson = function(id){
//The original business logic will apply based on URL Param ID
var defObj = $q.defer();
$http.get('demodata.json')
.then(function(res){
defObj.resolve(res.data[0]);
});
return defObj.promise;
}
return data;
});
})();
How about this:
function PropertyController($scope, $stateParams) {
gapi.client.realestate.get($stateParams.propertyId).execute(function(resp) {
$scope.property = resp;
});
}

Resources