I have the following Angular and HTML code to display a list of images and allow voting:
<script type="text/javascript">
var application = angular.module('Application', []);
application.service('ImageService', function ($http) {
return {
GetList: function (page) {
return $http.get('api/images', { params: { page: page } });
},
Vote: function (image) {
return $http.post('api/images/{key}/vote', { key: image.Key });
}
}
});
application.controller('ImageController', function ImageController($scope, ImageService) {
var page = 0;
$scope.images = [];
ImageService.GetList(page)
.success(function (data, status, headers, config) {
$scope.images = $scope.images.concat(data);
})
.error(function (data, status, headers, config) { });
$scope.vote = function (image) {
ImageService.Vote(image)
.success(function (data, status, headers, config) { })
.error(function (data, status, headers, config) { });
};
});
</script>
<div data-ng-app="Application" data-ng-controller="ImageController" class="gallery">
<div data-ng-repeat='image in images' class="image">
<img src="{{image.Url}}" alt="" />
<i class="icon-heart"></i>
<span>{{image.Votes}}</span>
</div>
</div>
Each image has an unique id, image.Id.
How can I disallow a user to vote the same image twice?
Use ng-hide to hide link if hasVoted is true.
<div class="gallery">
<div data-ng-repeat='image in images' class="image">
<img src="{{image.Url}}" alt="" />
<i class="icon-heart"></i>
<span>{{image.Votes}}</span>
</div>
</div>
Then modify controller to set voted to true. If it fails we will set it back to false. The reason to do it is to prevent multiple clicks on the button until we receive success back from the server:
$scope.vote = function (image) {
image.hasVoted = true;
ImageService.Vote(image)
.success(function (data, status, headers, config) { })
.error(function (data, status, headers, config) { image.hasVoted = false; });
};
The simplest tweak on the client side would be something like this:
$scope.vote = function (image) {
if (!image.voted) {
ImageService.Vote(image)
.success(function (data, status, headers, config) { image.voted = true })
.error(function (data, status, headers, config) { });
}
};
Simply flag the image as voted.
Related
I'm trying to write down a Controller that pass a var to a Factory in Angularjs.. The following code return (in console) the values, but I'm not been able to load that into my html page.
Just to record, yes, I'm starting in angularjs.
app.js
var myApp = angular.module('myApp',[]);
myApp.factory('eventData', function ($http, $q) {
delete $http.defaults.headers.common['X-Requested-With'];
return {
getEvent: function (id) {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'page' + id
}).
success(function (data, status, headers, config) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
};
});
myApp.controller('AngularJSCtrl',
function FeederController($scope, eventData) {
$scope.data = [];
for (var i = 0; i < 10; i++) {
eventData.getEvent(i).then(
function (data) {
$scope.data = data;
console.log($scope.data);
},
function (statusCode) {
console.log(statusCode)
});
}
}
);
page.html
<div ng-controller="AngularJSCtrl">
<div ng-repeat="patient in patients">
<businesscard>{{patient.name}}</businesscard>
</div>
</div>
Problem solved. I've searched for a while until get this right.
Thanks for #Claies and Brad Barrow for the tips :)
app.js
var myApp = angular.module('myApp',[]);
myApp.factory('patientsData', function ($http) {
delete $http.defaults.headers.common['X-Requested-With'];
return {
getPatients: function () {
return $http({
url: 'http://localhost/ucamradio/php/tst.php?campusId=1',
method: 'GET'
})
}
}
});
myApp.controller('AngularJSCtrl', function($scope, patientsData){
$scope.patients = [];
var handleSuccess = function(data, status) {
//$scope.patients = data;
$scope.patients.push(data);
console.log($scope.patients);
};
patientsData.getPatients().success(handleSuccess);
});
page.html
<div ng-controller="AngularJSCtrl">
<div ng-repeat="patient in patients">
<businesscard>{{patient.name}}</businesscard>
</div>
<!--
<div ng-repeat="patient in patients ">
<businesscard>{{patient.id}}</businesscard>
</div> -->
</div>
I have the following angular controller:
application.controller('ImageController', function ImageController($scope, ImageService) {
$scope.model = {
images: []
}
var list = function () {
ImageService.GetList()
.success(function (data, status, headers, config) {
$scope.model.images = $scope.model.images.concat(data.Images)
})
.error(function (data, status, headers, config) { });
}
$scope.vote = function (image) {
ImageService.Vote(image)
.success(function (data, status, headers, config) { })
.error(function (data, status, headers, config) { });
};
list();
});
The service returns a list of images as follows:
{"Images": [
{"Key":"22","Url":"http://www.domain.com/i/img22.jpg", "Votes": 120},
{"Key":"88","Url":"http://www.domain.com/i/img88.jpg", "Votes": 428}
]}
I display a list of images each having a vote button and the number of votes.
<div data-ng-repeat='image in model.images'>
<img data-ng-src="{{image.Url}}" alt="" />
VOTE
<span>{{image.Votes}}</span>
</div>
When a user votes an image I would like to disable the vote button, even if only for this page request, and increase the number of votes by one.
PLAN
My idea would be to add a property "HasBeenVoted" as False to each image after being loaded from the service and when the image is voted change it to true and increase its votes by one. And of course sync with the HTML to disable the Vote button and update the {{image.Votes}}
PROBLEM
How to include the HasBeenVoted in all image here:
$scope.model.images = $scope.model.images.concat(data.Images)
How to update HasBeenVoted and Votes Number in the model and HTML here:
$scope.vote = function (image) {
ImageService.Vote(image)
.success(function (data, status, headers, config) { })
.error(function (data, status, headers, config) { });
};
Could someone, please, help me out with this?
If you don't need to check serverside you could just change your JS/HTML as follows:
HTML
<div data-ng-repeat='image in model.images'>
<img data-ng-src="{{image.Url}}" alt="" />
<a ng-disabled="image.HasBeenVoted" href="" data-ng-click="vote(image)">VOTE</a>
<span>{{image.Votes}}</span>
</div>
Javascript
$scope.vote = function (image) {
image.HasBeenVoted = true;
image.Votes += 1;
ImageService.Vote(image)
.success(function (data, status, headers, config) { })
.error(function (data, status, headers, config) { });
};
This works because image.HasBeenVoted will be false initially and true for each image you vote on.
But this does not persist if you navigate. I suggest you extend the service to handle this server side. Your server should be responsible for this. Your response should have the property HasBeenVoted for the logged in user.
Edit: you could do the check in your controller instead, change your HTML + JS as follows:
CSS
.disabled {
opacity: .2;
}
HTML
<div data-ng-repeat='image in model.images'>
<img data-ng-src="{{image.Url}}" alt="" />
<a ng-class="{disabled: image.HasBeenVoted}" href="" data-ng-click="vote(image)">VOTE</a>
<span>{{image.Votes}}</span>
</div>
JS
$scope.vote = function (image) {
if (image.HasBeenVoted) { return; }
image.HasBeenVoted = true;
image.Votes += 1;
ImageService.Vote(image)
.success(function (data, status, headers, config) { })
.error(function (data, status, headers, config) { });
};
I have the following Angular and HTML code:
<script type="text/javascript">
var application = angular.module('Application', []);
application.service('ImageService', function ($http) {
return {
GetList: function () {
return $http.get('api/images');
},
}
});
application.controller('ImageController', function ImageController($scope, ImageService) {
ImageService.GetList()
.success(function (data, status, headers, config) {
$scope.images = data;
})
.error(function (data, status, headers, config) { });
});
</script>
<div data-ng-app="Application" data-ng-controller="ImageController" class="gallery">
<div data-ng-repeat='image in images' class="image">
<img src="{{image.Url}}" alt="" />
</div>
</div>
The API call is returning the following:
[
{"Key":"89207","Url":"http://somedomain.com/image89207.jpg"},
{"Key":"12321","Url":"http://somedomain.com/image12321.jpg"},
{"Key":"23434","Url":"http://somedomain.com/image23434.jpg"}
]
I would like to load the next page when the user scrolls down to the end of the page or when it clicks a button saying "Show More".
I also need to return on my JSON the NextPage value ...
The point is that if current page is "233" then next page might be "4545".
I think the API might need to return the next page value and a list of images.
How can I do this?
I agree with pankajparkar. You should handle 'show more' button, load more images and join it with $scope.images. ng-repeat will do remaining work. Here is code sample
<script type="text/javascript">
var application = angular.module('Application', []);
application.service('ImageService', function($http) {
return {
GetList: function(page) {
return $http.get('api/images', {
params: {
page: page
}
});
},
}
});
application.controller('ImageController', function ImageController($scope, ImageService) {
var page = 0;
$scope.images = [];
var load = function() {
ImageService.GetList(page)
.success(function(data, status, headers, config) {
$scope.images = $scope.images.concat(data);
})
.error(function(data, status, headers, config) {});
};
load();
$scope.loadMore = function() {
page++;
load();
}
});
</script>
<div data-ng-app="Application" data-ng-controller="ImageController" class="gallery">
<div data-ng-repeat='image in images' class="image">
<img src="{{image.Url}}" alt="" />
</div>
<div>
<button ng-click="loadMore()">load more</button>
</div>
</div>
<li ng-repeat="result in apiResult">
<span class="">{{result.id}}</span>
</li>
<form ng-submit="findone()">
<input type="text" ng-model="searchTerm" value=""></span>
<input class="btn-primary" type="submit" value="go">
</form>
The above is my template.
What is the "angular way" to bind the ng-model searchTerm, to the value of an individual {{result.id}} when a user clicks on this <span>{{result.id}}</span>?
Controller:
var app = angular.module('campaign', []);
function campaignCtrl($scope, $http) {
$scope.search = function() {
$http({method: 'GET', url: "http://localhost:3002/voters.json?token=17975700jDLD5HQtiLbKjwaTkKmZK7zTQO8l5CEmktBzVEAtY&street_name="+$scope.searchTerm}).
success(function(data, status, headers, config) {
$scope.apiResult = data.voters;
}).
error(function(data, status, headers, config) {
});
};
$scope.init = function(id) {
$http({method: 'GET', url: "http://localhost:3002/voters.json?token=17975700jDLD5HQtiLbKjwaTkKmZK7zTQO8l5CEmktBzVEAtY&street_name="+id}).
success(function(data, status, headers, config) {
$scope.apiResult = data.voters;
console.log(data.voters)
}).
error(function(data, status, headers, config) {
});
};
$scope.findone = function(searchTerm) {
$http({method: 'GET', url: "http://localhost:3002/voters.json?token=17975700jDLD5HQtiLbKjwaTkKmZK7zTQO8l5CEmktBzVEAtY&id="+searchTerm}).
success(function(data, status, headers, config) {
console.log(data);
$scope.apiResult = data.voters;
}).
error(function(data, status, headers, config) {
});
};
}
function indyCtrl($scope, $http) {
}
Not exactly sure about the question. I think you are looking for something like this
<li ng-repeat="result in apiResult">
<span class="" ng-click="searchTerm=result.id">{{result.id}}</span>
</li>
I have a page that contains an ng-repeat directive. The ng-repeat works when the page first loads, but I want to be able to use ng-click to refresh the contents of the ng-repeat. I have tried the following code but it doesn't work. Any suggestions?
<div ng-click="loadItems('1')">Load 1st set of items</div>
<div ng-click="loadItems('2')">Load 2nd set of items</div>
...
<table>
<tr ng-repeat="item in items">>
// stuff
</tr>
</table>
ItemsCtrl:
$scope.loadItems = function (setID) {
$http({
url: 'get-items/'+setID,
method: "POST"
})
.success(function (data, status, headers, config) {
$scope.items = data;
})
.error(function (data, status, headers, config) {
$scope.status = status;
});
};
I was hoping that my call to loadItems() would cause the ng-repeat directive to reload with the new data obtained from my server.
Add a broadcast in your callback and subscribe to it in your controller.
This should really be in a service btw
itemsService.loadItems = function (setID) {
$http({
url: 'get-items/'+setID,
method: "POST"
})
.success(function (data, status, headers, config) {
$scope.items = data;
$rootScope.$broadcast('updateItems', data);
})
.error(function (data, status, headers, config) {
$scope.status = status;
});
};
In your controller:
$scope.$on("updateItems",function(d){
$scope.items = d;
});
So whenever you ng-click="update(id)"
$scope.update = function(id){
itemsService.loadItems(id);
}
Your items will automatically update because it is subscribed.