Angular factory routeParam variable not changing - angularjs

angular.module('app')
.factory('Answers', function ($resource, $routeParams, $location) {
return $resource('api/answers?questionid=' + $routeParams.questionId, {
answerId: '#_id'
}, {
update: {
method: 'PUT'
}
});
});
$scope.findAnswers = function() {
Answers.query(function(answers) {
$scope.answers = answers;
});
};
It seems like the $routeParams variable isn't being updated as I navigate around my app through different routes. Is this the case w/ services? I'm guessing I should define the variable in my controller and then pass it into my service?
EDIT:
angular.module('intquestApp')
.factory('Answers', function ($resource, $routeParams, $location) {
return {
get: function(questionId) {
return $resource('api/answers?questionid=' + questionId, {
update: {
method: 'PUT'
}
});
}
};
});
Answers.get($routeParams.questionId, function(answers) {
console.log(answers);
$scope.answers = answers;
});

I believe the approach is to inject $routeParams into your Controller instead and pass the value to the service.
See here: Use $routeParams in service
so inside your Controller:
Answers.get(passRouteParamValueHere, function(answers) {
$scope.answers = answers;
});
EDIT
Why do you have update within get? Here's something you could try but haven't tested it:
.factory('Answers',['$resource', function ($resource) {
return $resource('/api/answers/?questionid=' + questionId, {}, {
get: { method: 'GET'}
});
}])
but I prefer this approach:
.factory('Answers',['$resource', function ($resource) {
return $resource('/api/answers/:qid', {}, {
get: { method: 'GET'}
});
}])
and then:
Answers.get({qid: questionIDFromRouteParam}, function(answers) {
$scope.answers = answers;
});
Just a little cleaner

Related

Moving code from controller to a factory breaks the code, why?

I'm moving my code from the .controller to a factory
here is the code that works from the controller
.controller('ChatsCtrl', function ($scope, $http, $rootScope) {
$http.get('http://<my_ip>:<my_port>/chats', { params: { user_id: $rootScope.session } }).success(function (response) {
$scope.chats = response;
});
})
I want this to be refactored to a factory so the controller looks like this
.controller('ChatsCtrl', function ($scope, Chats) {
$scope.chats = Chats.all();
})
So the factory is like this
.factory('Chats', function() {
return {
all: function ($scope, $http, $rootScope) {
return $http.get('http://<my_ip>:<my_port>/chats', { params: { user_id: $rootScope.session } }).success(function (response) {
$scope.chats = response;
});
}
};
});
So when I move the code to the factory it doesn't pull anything from my database. I have referenced the 'Chats' factory in the controller but it doesn't seem to pull the data through.
Return the promise to set and assign it to the scope in the controller. So more like this.
.controller('ChatsCtrl', function ($scope, Chats) {
Chats.all().success(function (data) {
$scope.chats = data;
})
})
.factory('Chats', function($http, $rootScope) {
return {
all: function () {
return $http.get('http://<my_ip>:<my_port>/chats',
{ params: { user_id: $rootScope.session } })
}
};
});
You can return a promise from the factory and do .success in the controller(optionally with a cache in the factory if your data doesn't change)
.factory('Chats', function() {
return {
all: function ($scope, $http, $rootScope) {
return $http.get('http://<my_ip>:<my_port>/chats', { params: { user_id: $rootScope.session } })
}
};
});
.controller('ChatsCtrl', function ($scope, Chats) {
Chats.all().success(function (response) {
$scope.chats = response;
});
})

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
};
});

How to implement a generic HTTP service in AngularJS?

In my angular module I wrote a generic http handler for all my ajax requests.'
I was expecting that I could use the service across controllers, but my problem is the promise seems to be global.
Once ControllerOne uses the mapi_loader service, when I load AnotherController (by ng-click="go('/$route_to_load_another_controller')"), AnotherController is loaded a promise that has already returned from ControllerOne even though the URL they fetch are totally different.
So I guess my question is how do I write a service I could use across controllers? Do I really need to write a separate service for each controller where their only difference in code is the URL passed for $http.jsonp?
angular.module('myAppControllers',[])
.service('mapi_loader', ['$http', function($http) {
var promise;
var myService = {
fetch: function(url) {
if ( !promise ) {
promise = $http.jsonp(url)
.then(function (response) {
return response.data.nodes;
});
}
return promise;
}
};
return myService;
}])
.controller('ControllerOne', ['$scope', 'mapi_loader', function ($scope, mapi_loader) {
mapi_loader
.fetch("http://host.com/mapi_data_for_controller_one?callback=JSON_CALLBACK")
.then(function(data) {
$scope.useme = data;
});
}])
.controller('AnotherController', ['$scope', 'mapi_loader', function ($scope, mapi_loader) {
mapi_loader
.fetch("http://host.com/mapi_data_for_another_controller?callback=JSON_CALLBACK")
.then(function(data) {
$scope.useme = data;
});
}])
;
try something like this
angular.module('myAppControllers',[])
.service('mapi_loader', function($http) {
var alreadyLoading = {};
return {
fetch: function(url) {
if ( url in alreadyLoading ) {
return alreadyLoading[url];
}
return alreadyLoading[url] = $http.jsonp(url)
.then(function (response) {
delete alreadyLoading[url];
return response.data.nodes;
});
}
};
})
.controller('ControllerOne', function ($scope, mapi_loader) {
...
})
.controller('AnotherController', function ($scope, mapi_loader) {
...
});

AngularJS Factory Parameter

I'm trying to send a parameter to an angularjs service. Here is my service code :
angular.module('skyBiometryServices', ['ngResource'])
.factory('Facedetect', function( $resource ) {
return $resource('skyBiometry/facedetect', {}, {
query: {
method : 'GET',
params : {imageUrl: "http://cdn1-public.ladmedia.fr/var/public/storage/images/dossiers/presidentielles-2012/les-news-sur-les-presidentielles-2012/exclu-public-cauet-pour-ces-presidentielles-personne-ne-me-fait-rever-209063/2064021-1-fre-FR/Exclu-Public-Cauet-Pour-ces-presidentielles-personne-ne-me-fait-rever-!_portrait_w674.jpg"},
isArray: false
}
})
});
In my controller i have this :
function IndexCtrl($scope,Facedetect) {
$scope.text = Facedetect.query();
}
How can i send the imageurl into my services from the controller ? Something like this
function IndexCtrl($scope,Facedetect) {
$scope.text = Facedetect.query('MY IMAGE URL');
}
In advance thanks.
You can write your factory like this
app.factory('Facedetect',function($resource) {
return {
query: function(image_url) {
return $resource('skyBiometry/facedetect', {}, {
query: { method: 'GET', params: {imageUrl:image_url}, isArray: false }
}).query();
}
}
});
Now in your controller you can write
function IndexCtrl($scope, Facedetect) {
$scope.text = Facedetect.query("YOUR/IMAGE/URL");
}
If i understand correctly, you want something like that:
app.factory('myFactory',function(){
return{
prop: '',
setProp: function(newProp){
this.prop = newprop;
}
}
});
You should watch this:
https://egghead.io/lessons/angularjs-providers
And read this:
AngularJS: Service vs provider vs factory
With more research i found a solution :
factory('Facedetect', function( $resource ) {
return $resource('skyBiometry/facedetect', {}, {
query: {
method : 'GET',
params : {imageUrl: "http://cdn1-public.ladmedia.fr/var/public/storage/images/dossiers/presidentielles-2012/les-news-sur-les-presidentielles-2012/exclu-public-cauet-pour-ces-presidentielles-personne-ne-me-fait-rever-209063/2064021-1-fre-FR/Exclu-Public-Cauet-Pour-ces-presidentielles-personne-ne-me-fait-rever-!_portrait_w674.jpg"},
isArray: false
}
})
});
function IndexCtrl( $scope, $routeParams, Facedetect ) {
$scope.imageurl = 'http://flepi.net/images/personne-tendue.jpg';
$scope.text = $scope.text = Facedetect.get({imageUrl: $scope.imageurl});
}
I don't know if it's the best way but it works.

Is there a way I can return a promise from a $resource without needing to use $q?

I have coded the following service:
angular.module('App')
.factory('TestService', ['$http', '$q', '$resource', function (
$http, $q, $resource) {
var TestResource = $resource('/api/Tests', {}, {
saveData: { method: 'PUT' },
deleteData: { method: "DELETE", params: { TestId: 0 } }
});
var factory = {
query: function (selectedSubject) {
var deferred = $q.defer();
TestResource.query({ subjectId: selectedSubject },
function (resp) {
deferred.resolve(resp);
}
);
return deferred.promise;
//return Test.query({ subjectId: selectedSubject });
}
}
return factory;
}]);
In my controller I am calling it this way:
TestService.query($scope.selectedSubject)
.then(function (result) {
$scope.gridData = result;
}, function (result) {
alert("Error: No data returned");
});
Is there a way that I could cut out a few lines of code by not having $q in my service. Is there a way that I could return a promise from the $resource? I have tried the commented out code but that gives me an error saying there is no ".then" method.
$resource can't return a promise in the current stable version of Angular (1.0.8), but it looks like it'll come in version 1.2. It was added in v1.1.3 (v 1.1 is the unstable branch):
$resource: expose promise based api via $then and $resolved (dba6bc73)

Resources