I want to fetch particular category by id. I have populated dummyjson data using $http method.I am unable to do this. I have pass id from my services to controller but it returns null. Here i my code
service.js:
(function() {
angular.module('myApp')
.factory('registerService', function ($http) {
var category=[];
return {
getAll:function(){
return $http.get('json/dummyJson.json').then(function(response){
category=response.data;
return category;
});
},
getUser:function(category_id)
{
for(var i=0;i<category.length;i++){
console.log(category.length);
if(category[i].id === parseInt(category_id)){
return category[i];
}
}
return null;
}
}
});
})();
controller.js:
(function() {
angular.module('myApp').controller('registrationCtrl1', function ($scope, $stateParams, registerService) {
console.log('inside registerCtrl2');
$scope.categoryName=registerService.getUser($stateParams.category_id);
console.log($stateParams.category_id);
console.log($scope.categoryName);
});
})();
You are assuming that category will have value within getUser, but that won't happen. The only place where category is populated is getAll, but since you are not calling getAll, category is not populated. Chnage your method as below and it will work:
getUser: function(category_id) {
return $http.get('json/dummyJson.json').then(function(response){
category=response.data;
for(var i=0;i<category.length;i++) {
console.log(category.length);
if(category[i].id === parseInt(category_id)){
return category[i];
}
}
return null;
});
}
Since your method returns a promise now you need to handle the promise in a callback in your controller:
angular.module('myApp').controller('registrationCtrl1', function ($scope, $stateParams, registerService) {
console.log('inside registerCtrl2');
registerService.getUser($stateParams.category_id)
.then(function (response) {
$scope.categoryName= response;
console.log($stateParams.category_id);
console.log($scope.categoryName);
});
});
Related
In angularJS, With one call, when get the service response need access that json value in multiple controllers but in same page
I have two controller js file and both controllers are called in the same page when I called the service "this.getNavigationMenuDetails" in the first controller.js and as well as called in the controller2.js file as well. without timeout function, I want to access that same response which I get it from the "this.getNavigationMenuDetails" service in controller2.js. But it happened that service call twice in the page. I don't want to call the same service twice in a page.
When js are loading that time both controllers are called in the same layer then getting the response from the service so on the second controller2.js file code is not execute after the response. How can I solve this issue so that only one call i can get the response and access this response in controller2.js also.
controler1.js
var app = angular.module("navApp", []);
app.controller("navCtrl", ['$scope', 'topNavService', '$window', function ($scope, $timeout, topNavService, $window) {
$scope.menuItemInfo = {};
/*Navigation Menu new Code */
$scope.getNavigationDetails = function () {
topNavService.getNavigationMenuDetails().then(function (result) {
$scope.menuItemInfo = result;
angular.forEach($scope.menuItemInfo.items, function (val, key) {
if (val.menuTitle ===
$window.sessionStorage.getItem('selectedNavMenu')) {
if ($scope.menuItemInfo.items[key].isEnabled) {
$scope.menuItemInfo.items[key].isActive = 'highlighted';
} else {
$window.sessionStorage.removeItem('selectedNavMenu');
}
}
if (val.menuTitle === 'Find a Fair' && !val.hasSubMenu) {
$scope.menuItemInfo.items[key].redirectTo = appConfig.findafairpageurl;
}
});
});
};
$scope.init = function () {
if ($window.location.pathname.indexOf('all-my-fairs.html') > 0) {
if (angular.isDefined($cookies.get('cpt_bookfair'))) {
$cookies.remove('cpt_bookfair', {
path: '/'
});
}
}
$scope.getNavigationDetails();
$scope.callOnLoad();
};
$scope.init();
}]);
app.service('topNavService', ['$http', '$timeout', '$q'function ($http, $timeout, $q) {
var menuInfo;
this.getNavigationMenuDetails = function () {
if (!menuInfo) {
// If menu is undefined or null populate it from the backend
return $http.get("/etc/designs/scholastic/bookfairs/jcr:content/page/header-ipar/header/c-bar.getMenuDetails.html?id=" + Math.random()).then(function (response) {
menuInfo = response.data;
return menuInfo;
});
} else {
// Otherwise return the cached version
return $q.when(menuInfo);
}
}
}]);
Controller2.js
var app = angular.module('bookResourcePage', []);
app.controller('bookResourceCtrl', ['topNavService', '$scope', function (topNavService, $scope) {
$scope.topInfo = '';
topNavService.getNavigationMenuDetails.then(function success() {
$scope.productId = $scope.topInfo.isLoggedin;
$scope.linkParam = '?productId=' + $scope.productId;
}, function failure() {
console.error("something bad happened");
});
}]);
The service would work better if it cached the HTTP promise instead of the value:
app.service('topNavService', function ($http) {
var menuInfoPromise;
this.getNavigationMenuDetails = function () {
if (!menuInfoPromise) {
// If menu is undefined or null populate it from the backend
menuInfoPromise = $http.get(url);
};
return menuInfoPromise;
};
});
The erroneous approach of caching the value introduces a race condition. If the second controller calls before the data arrives from the server, a service sends a second XHR for the data.
You can do this with following approach.
Service.js
app.service('topNavService', function($http) {
var menuInfoPromise;
var observerList = [];
var inProgress = false;
this.addObserver(callback) {
if (callback) observerList.push(callback);
}
this.notifyObserver() {
observerList.forEach(callback) {
callback();
}
}
this.getNavigationMenuDetails = function() {
if (!menuInfoPromise && !inProgress) {
inProgress = true;
// If menu is undefined or null populate it from the backend
menuInfoPromise = $http.get(url);
this.notifyObserver();
};
return menuInfoPromise;
};
});
You have to make a function in service to add your controller's function on list. then each controller will register their get function on service and call service method to get data. first call will make service variable inProgress to true. so it will prevent for multiple server request. then when data available to service then it will call its notifyObserver function to message for all controller by calling their function.
Controller 1
app.controller('ctrl1', ['service', '$scope', function(service, $scope) {
service.addObserver('getData1'); //name of your controller function
$scope.getData1() {
service.getNavigationMenuDetails.then(function success() {
$scope.productId = $scope.topInfo.isLoggedin;
$scope.linkParam = '?productId=' + $scope.productId;
}, function failure() {
console.error("something bad happened");
});
}
$scope.getData1()
}]);
Controller 2
app.controller('ctrl1', ['service', '$scope', function(service, $scope) {
service.addObserver('getData2'); //name of your controller function
$scope.getData2() {
service.getNavigationMenuDetails.then(function success() {
$scope.productId = $scope.topInfo.isLoggedin;
$scope.linkParam = '?productId=' + $scope.productId;
}, function failure() {
console.error("something bad happened");
});
}
$scope.getData2()
}]);
with this approach you can real time update data to different controllers without have multiple same request to server.
I have a service to get (with array) all post from a server. I need to filter this array by id and show only this post in a single page.
In the service I have this code.
.service('PostAPI', function($http) {
this.getAll = function() {
return $http.get("ajax/getAllPosts.php");
}
this.getOne = function(data) {
return $http.get("ajax/searchPost.php?postID=" + data);
}
this.delete = function(data) {
if (confirm("Are you sure to delete this line?")) {
return $http.delete("ajax/deletePost.php?postID=" + data);
}
}
this.update = function(data) {
return $http.put("ajax/updatePost.php?postID" + data);
}
this.create = function() {
return $http.post("ajax/addPost.php");
}
})
In the controller
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
GetPost();
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).success(function(data) {
$scope.post = data;
console.log($scope.post);
});
};
In post HTML I have this.
<div>
<div>{{post.TASK}}</div>
<div>{{post.STATUS}}</div>
<b>Back</b>
</div>
I'm not able to get any data to show in the page, and also, i have no errors in my console. ¿Any idea?
Check your ajax/searchPost.php?postID= api that is this api returning single object or array, If this api returning object than it should work but If you getting array of single element in response of api then in your api success code use first element of array by data[0].
Controller code
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
GetPost();
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).success(function(data) {
$scope.post = data[0];
console.log($scope.post);
});
};
use then instaed of success. .then returns a promise so that you can handle the asynchrounous calls.
Also you are calling the getPost() method before function definition. So it may not get the promise.
call your getPost(), method after the function definition and check, so that it can receive the promise.
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).then(function(data) {
$scope.post = data[0];
console.log($scope.post);
});
};
GetPost();
Currently writing a prototype app in Ionic, pretty new to ionic and angular. I've written a small JSON API with about 25 objects in it, I've been able to display the list of them on a page we'll call "Library", I'm trying now to use those list items as links to an individual page for each item we will call a "Lesson". The variable $scope.lessonId is being set properly in the controller but being set as undefined in the service. Is it possible to achieve what I'm trying to, or am I just flat out doing this wrong?
.controller('LibraryLessonCtrl', function($scope, $stateParams, LessonService) {
$scope.lessonId = $stateParams.libraryId;
console.log($scope.lessonId);
LessonService.getLessonId()
.then(function(response){
$scope.lesson = response;
console.log($scope.lesson);
});
})
.service ('LessonService', function($http){
return { getLessonId: function() {
return $http.get('api/postsAPI.json')
.then(function (response, lessonId) {
console.log(lessonId);
for(i=0;i<response.data.length;i++){
if(response.data[i].post_id == lessonId){
return response.data[i];
}
}
});
}
};
})
You have to pass your $scope.lessonId variable to your service call if you like to use the value inside your service.
.controller('LibraryLessonCtrl', function($scope, $stateParams, LessonService) {
$scope.lessonId = $stateParams.libraryId;
console.log($scope.lessonId);
LessonService.getLessonId($scope.lessonId)
.then(function(response){
$scope.lesson = response;
console.log($scope.lesson);
});
}).service ('LessonService', function($http){
return { getLessonId: function(lessonId) {
return $http.get('api/postsAPI.json')
.then(function (response) {
console.log(lessonId);
for(i=0;i<response.data.length;i++){
if(response.data[i].post_id == lessonId){
return response.data[i];
}
}
});
}
};
})
You could do it by passing Id to service and storing it there. Please try not to pass $scope variable to service as it is not a good practice. You can do following:
.service ('LessonService', function($http){
var lessionId;
return {
/*other methods*/
setLessionId: function(id) {
lessionId = id;
},
getLessionId: function(){
return lessionId;
}
};
})
I have 3 factory functions that I would like to chain together to be used in a resolve stanza of a route:
1st function is a simple REST call to $http:
app.factory('services', ['$http', '$q', function ($http, $q) {
var serviceBase = 'services/';
var obj = {};
obj.getSelect = function (db, table, columns, keys) {
return $http.post(serviceBase + 'getSelect', {
selectDB: db,
selectTable: table,
selectColumn: columns,
selectKeys: keys
}).then(function (results) {
return results;
});
};
// more objects follow
}
It is used by the next function that simply calls services.getSelect to retrieve some records:
app.factory('myFunctions', ['services', '$q', function (services, $q) {
return {
fGetData: function () {
services.getSelect(
'myDB', // DB
'tableInDB', // Table
"*", // Columns
"" // Keys
).then(
function (retObj) {
return $q.all (retObj);
console.log('myFunctions.fGetData', retObj);
}
)
}
}
}]);
The last function calls myFunctions.fGetData. Its purpose is to return values to the resolve stanza:
app.factory("getInitData",['myFunctions','$q', function (myFunctions, $q) {
return function () {
var initData = myFunctions.fGetData();
return $q.all( {initData: results} ).then(function (results) {
return {
initDataReturn: results
};
console.log('getInitData', results);
});
}
}]);
and finally the resolve stanza:
app.config( ['$routeProvider', 'myConst', function ($routeProvider) {
$routeProvider.when(myConst.adminButtonURL, {
templateUrl: '/myTemplateURL',
controller: myControler,
resolve: {
initDataObj: function(getInitData){
return getInitData();
}
}
}
}]);
In the controller the initDataObj is returned:
app.controller('myController', function ($scope, nitDataObj {
$scope.surveyGroup = initDataObj.initData;
});
The console logs always show that 'getInitdata' always fires first and the return is a null object.
The function myFunctions.fGetData always fires first and the correct data is returned.
To miss-quote a song from He Haw: "I've searched the world over and I thought I'd find the answer (true love is lyric)", but while there have been very interesting bits of clues including
http://busypeoples.github.io/post/promises-in-angular-js/ &
http://www.dwmkerr.com/promises-in-angularjs-the-definitive-guide/
nothing has had the complete answer.
Thanks to all.
ok i think in part this has to do with the way you are using $q
$q.all take an array or an object containing promises
https://docs.angularjs.org/api/ng/service/$q
in your services factory you are resolving the promise and then returning the results
and then in myFunctions you are taking the returned value and trying to give it to $q.all which doesnt accept what you're giving it
looks like your wanting to keep sending a promise back from each factory you could do something like
app.factory('services', ['$http', function ($http) {
var serviceBase = 'services/';
var obj = {};
obj.getSelect = function (db, table, columns, keys) {
return $http.post(serviceBase + 'getSelect', {
selectDB: db,
selectTable: table,
selectColumn: columns,
selectKeys: keys
});
};
// more objects follow
}
app.factory("myFunctions", ["$q", "services", function($q, services){
return {
fGetData: function(){
var deferred = $q.defer();
services.getSelect()
.success(function(results){
// do something with the data
deferred.resolve(results);
});
return deferred.promise;
}
};
}]);
app.factory("getInitData",['myFunctions', function (myFunctions) {
return function () {
myFunctions.fGetData()
.then(function(data){
// do something with the data
});
}
}]);
How can I wait with my function till the $http request is finished?
My services.js looks as follows:
var app = angular.module('starter.services', []);
app.factory('Deals', function($http) {
function getDeals() {
$http.get('http://www.domain.com/library/fct.get_deals.php')
.success(function (data) {
var deals = data;
return deals;
})
.error(function(err){
});
}
return {
all: function() {
return getDeals();
},
get: function(keyID) {
//...
}
}
});
My controllers.js looks like:
var app = angular.module('starter.controllers', []);
app.controller('DealCtrl', function($scope, Deals) {
$scope.deals = Deals.all();
console.log($scope.deals);
});
The console.log in my controllers.js file outputs "undefined", but when I output the deals in the getDeals() function it contains the correct array which I get from my server.
What am I doing wrong?
$http and all of the async services in angularjs return a promise object. See promise api.
You need to use then method to assign it to a value in the scope.
So your controller:
app.controller('DealCtrl', function($scope, Deals) {
Deals.all().then(function (deals) {
$scope.deals = deals;
console.log($scope.deals);
});
});
Your service
app.factory('Deals', function($http) {
function getDeals() {
return $http.get('http://www.domain.com/library/fct.get_deals.php')
.success(function (data) {
var deals = data;
return deals;
});
}
return {
all: function() {
return getDeals();
},
get: function(keyID) {
//...
}
}
});