To begin sorry for my English.
I made some search about this problem, but nothing works for me.
My problem is simple :
I have an upvote system, where users can upvote (like Stackoverflow). But the problem is that users can upvote multiple times (and it's not very well ..).
I tried to make a button with ng-disabled, but if i do this, users can only vote one time for all the posts (I mean if they upvoted "Post A", they can't upvote "Post B").
Here is my controller function :
$scope.incrementUpvotes = function(post) {
posts.upvote(post);
};
Here is my factory function :
o.upvote = function(post){
return $http.put('/posts/' + post._id + '/upvote', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
post.upvotes += 1;
});
};
And here the html :
<span class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(post)"></span>
If someone could help me it would be great ! Thanks in advance !
Please try to use button or input instead of span. Because disabled does not work in a span.
<button id="{{ post._id + 'upvote' }}" class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(post)"></button>
Then set disabled attribute of your upvote button true after the upvote action.
o.upvote = function(post){
return $http.put('/posts/' + post._id + '/upvote', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
post.upvotes += 1;
angular.element(document.getElementById(post._id + 'upvote' ))[0].disabled = true;
});
};
This is more of an architectural question than it is javascript/angularjs question. There are many ways to do this. But the idea is to store in database and persist upvote information, otherwise users can just refresh the page and upvote again.
Most direct solution is: You have to store your vote information on the backend at the user level. When you query the user information, store a list of up-voted posts like this:
myDataService should look like this:
angular.module("app", []).service("myDataService", ["$http","$q","$rootScope", function myDataService($http, $q, $rootScope) {
var myDataService = this;
myDataService.getPostsUpvoted = function(userId) {
var defer = $q.defer();
//here you format your payload to deliver userId to the api backend
var payload = { userId: userId };
//your api backend 'getpostsupvoted' should accept a userId, then in return it should
//deliver a list of posts upvoted by that user
$http.post("/api/getpostsupvoted", payload).then(function (data, status, headers, config) {
//call success
defer.resolve(data);
}, function(data, status, headers, config) {
//an error occurred
defer.reject(data);
});
return defer.promise;
}
return myDataService;
})];
Then, this is how you'll use the service in your controller.
//inject scope and myDataservice into controller
angular.module("app", []).controller("MainCtrl", ["$scope", "myDataService", function($scope, myDataService) {
//create a new array to hold a list of upvotes
$scope.user.upVoted = [];
myDataService.getPostsUpvoted($scope.user.id).then(function(data) {
//set upvoted array to data
$scope.user.upVoted = data;
}, function(error) {
//blah an error occurred
});
})];
In your controller, provide a function to check if a post has already been upvoted.
$scope.IsUpvotedAlready = function(postId) {
if($scope.user.upVoted.indexOf(postId) > -1)
return true;
return false;
}
You'll also have to push the post._id to the upVoted array and keep it there.
$scope.incrementUpvotes = function(post) {
//check if it's already been upvoted, then do nothing
if($scope.user.upVotes.indexOf(post._id) > -1)
return;
posts.upvote(post);
$scope.user.upVoted.push(post._id);
};
Then, in your ng-repeat directive where you display the post, check if the list of upvotes contain the post._id.
<div ng-repeat="post in posts">
<div ng-if="IsUpvotedAlready(post._id)">
<!-- display something since already upvoted !-->
</div>
{{ post }}
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With