custom pagination to table using Angular JS - angularjs

I'm trying to add pagination for my code. I'm able to add number of rows after clicking
add button. But, getting confused how to apply pagination custom.
Any advice on how to implement?
This is my fiddle http://jsfiddle.net/H2ps5/185/
var myApp = angular.module('myApp',[]);
myApp.controller('ctrl',function($scope){
$scope.firstname = 'Nizam'; // Set First Name on Page Load.
$scope.lastname = 'Ali'; // Set Last Name on Page Load.
$scope.users = []; // Define "users" Array.
/**
* Adding a new user.
*/
$scope.newuser = function(){
if($scope.firstname != "" && $scope.lastname != ""){ // If Values are not Empty.
this.users.push( // Push the values of First Name & Last Name in "users" Array.
{
firstname:$scope.firstname, // Key value pair.
lastname:$scope.lastname
}
);
$scope.firstname = ''; // Clear First Name
$scope.lastname = ''; // Clear Last Name
} else {
alert("Please fill values");
}
}
$scope.remove = function(user){ // Removing the user.
$scope.users.splice($scope.users.indexOf(user),1);
}
});
Kindly give me suggestions in which way I need to go

Diretive should be a way.
Make your own directive to handle how to manipulate the DOM when number of users in the scope gets to 10 or 20 or whatever you want.
Maybe another one for nav links between pages.

Related

cant remove selected only from table - angular

http://plnkr.co/edit/WFONNlAEIeN8K9DEJCqV?p=catalogue
i traying to delete/remove only the selected row
but no success.
remove function
$scope.removeTrainee = function(trainee){
var removeTrainee = $scope.trainees.indexOf(trainee);
$scope.trainees.splice(removeTrainee, 1);
};
the select function
$scope.selectedRow = null; // initialize our variable to null
$scope.setClickedRow = function(index){ //function that sets the value of selectedRow to current index
$scope.selectedRow = index;
};
tried to implement the selectedrow in ng-if or ng-click with && sign
no nothing
the remove function works, but not with selected one.
help please
To take the row selected you $scope.selectedRow so your funcion should be something like this:
$scope.removeTrainee = function(trainee){
var removeTrainee = $scope.trainees.indexOf(trainee);
$scope.trainees.splice($scope.selectedRow, 1);
};
Anyway I recommend you inplement the delete function in another way, more intuitive, for example adding a class to the selected row after clicking in it or adding a new row with a checkbox, to know which row is selected.
And you could also inprove your addTrainee function:
$scope.addTrainee = function(){
$scope.trainees.push(
$scope.newTreinee
);
$scope.newTreinee = {};
};
Hope this solution helps you.

Angular ng-repeat not updating after splice

I am working on a Angular Material site and using ng-repeat to populate a table. The list generated by the ng-repeat contains a list of users (the users array is populated by a RESTFul query).
Each "item-content" of the ng-repeat has a "Delete" button to delete/splice the item/user out of the array.
If I have no filters applied to the ng-repeat statement...when I splice the index of the selected user out of the array....the UI/DOM is updated and the user is removed from the list.
If I apply a filter (filters by the first letter of the last name and only shows those results)...when I splice the index out of the array...the UI/DOM is NOT updated and user remains in the list (from what I can tell from walking through the delete function from the console...the array is updated and the index/user is removed).
I filter being used is a custom angular filter and takes one input (the starting letter of the last name you want to filter on).
app.filter('startsWith', function () {
return function (items, letterMatch) {
var re = new RegExp("^[" + letterMatch.toUpperCase() + letterMatch.toLowerCase() + "]$");
var filtered = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
var lastNameLetter = item.user.name.substr(item.user.name.indexOf(' ') + 1, 1);
if (re.test(lastNameLetter)) {
filtered.push(item);
}
}
return filtered;
};
});
Here is the ng-repeat statement:
<md-item ng-repeat="user in ddUsers | startsWith:selectedFilter | startFrom:currentPage*pageSize | limitTo:pageSize">
In the controller...I am using Dialog Prompt (part of the Angular Material 1.1 RC framework) to initiate/confirm the Delete and proceed with the splice.
$scope.showPrompt = function(ev,index,user) {
// Appending dialog to document.body to cover sidenav in docs app
var confirm = $mdDialog.prompt()
.title('Delete User?')
.textContent('Type in DELETE to confirm deletion of the user.')
.placeholder('DELETE')
.ariaLabel('Delete User')
.targetEvent(ev)
.ok('Delete')
.cancel('Cancel');
$mdDialog.show(confirm).then(function(result) {
if(result=="DELETE")
{
$scope.ddUsers.splice(index, 1);
$scope.showSimpleToast('Successfully deleted ' + user.user.name);
}
else
{
$scope.showSimpleToast('Did not confirm properly');
}
}, function() {
$scope.showSimpleToast('Cancelled deletion for ' + user.user.name);
//var message = $scope.filterLastName(user.user.name);
//$scope.showSimpleToast(message);
});};
When the controller loads...I have a init function that executes and populates ddUsers from a custom angular factory:
var init = function () {
$scope.ddUsers = $UserList.UserList;
}
init();
I am not sure why ng-repeat is not updating after the splice when a filter is applied. If I have no filter on the ng-repeat, ng-repeat does update the UI/DOM to reflect the change and you don't see the user anymore.
While it is not shown how you call the function I assume you are passing in $index from view.
The problem with doing that is that $index will not be the same index for filtered array as for the original array so you would be splicing the wrong element out of the main data array
You need to do your own indexing by passing in the actual object.
I will also assume that user is that object so you would do:
if(result=="DELETE")
{
var idx = $scope.ddUsers.indexOf(user);
if(idx > -1 ){// make sure can index this object
$scope.ddUsers.splice(idx, 1);
$scope.showSimpleToast('Successfully deleted ' + user.user.name);
else{
// Ooops ... can't find it
}
}

Trouble filtering angular-meteor collection with infinite-scroll support

I'm trying to create an interactive photo database where the user can sort through photos and filter by user, check multiple categories he or she is interested in, and sort the filtered data by date, number of favorites, etc. The filter/sorting criteria are selected by the user on the DOM and are stored from the client side to $scope.model. The quantity of data visible to the user would be controlled with infinite scroll.
I've created a repository of this example, and I've deployed it here. I've reproduced some of the relevant code from scroll.controller.js below:
Code
// infinite-scroll logic & collection subscription //
$scope.currentPage = 1;
$scope.perPage = 12;
$scope.orderProperty = '-1';
$scope.query = {};
$scope.images = $scope.$meteorCollection(function() {
query={};
// if filtered by a user...
if ($scope.getReactively('model.shotBy')) {
query.shotBy = $scope.model.shotBy;
};
// if category filter(s) are selected...
if ($scope.getReactively('model.category', true)) {
if ($scope.model.category.length > 0){
var categories = [];
for (var i=0; i < $scope.model.category.length; i++){
categories.push($scope.model.category[i]);
}
query.category = {$in: categories};
}
};
$scope.currentPage = 1; // reset
return Images.find(query, { sort: $scope.getReactively('model.sort')});
});
$meteor.autorun($scope, function() {
if ($scope.getReactively('images')){
$scope.$emit('list:filtered');
}
});
$meteor.autorun($scope, function() {
$scope.$meteorSubscribe('images', {
limit: parseInt($scope.getReactively('perPage'))*parseInt(($scope.getReactively('currentPage'))),
skip: 0,
sort: $scope.getReactively('model.sort')
});
});
$scope.loadMore = function() {
// console.log('loading more');
$scope.currentPage += 1;
};
Problem
I can scroll through the images fine, and the infinite-scroll feature seems to work. However, when I attempt to filter the images from the DOM, the only filtered results are those which were initially visible before scrolling, and scrolling doesn't make the rest of the images that meet the criteria show, despite using $scope.$emit to signal ngInfiniteScroll to load more (documentation).
EDIT: If the initial filtered list does, in fact, reach the bottom, scrolling will append properly. It seems to not append only if the initial filtered list doesn't reach the bottom of the screem.
Question
What can I change to make ngInfiniteScroll behave as I would expect on a filtered collection?
Any help, thoughts, or suggestions would be appreciated, and let me know if there's anything else you'd like to see. Thank you!
Well, it took almost all day to figure out, but I now have a working example at this Github repository and deployed here.
To summarize, I found I need to filter at both the collection and subscription levels to cause perPage to apply properly and for ngInfiniteScroll functioning. Also, I needed to send an event via $scope.$emit to ngInfiniteScroll to tell it to fire again in case the images array was too small and didn't reach the edge of the screen. See the Github repository for more details, if you're interested.
Updated relevant code
// infinite-scroll logic & collection subscription //
$scope.currentPage = 1;
$scope.perPage = 12;
$scope.query = {};
function getQuery(){
query={};
// if filtered by a user...
if ($scope.getReactively('model.shotBy')) {
query.shotBy = $scope.model.shotBy;
};
// if category filter(s) are selected...
if ($scope.getReactively('model.category', true)) {
if ($scope.model.category.length > 0){
var categories = [];
for (var i=0; i < $scope.model.category.length; i++){
categories.push($scope.model.category[i]);
}
query.category = {$in: categories};
}
};
return query;
}
$meteor.autorun($scope, function(){
$scope.images = $scope.$meteorCollection(function() {
$scope.currentPage = 1; // reset the length of returned images
return Images.find(getQuery(), { sort: $scope.getReactively('model.sort')});
});
$scope.$emit('filtered'); // trigger infinite-scroll to load in case the height is too small
});
$meteor.autorun($scope, function() {
$scope.$meteorSubscribe('images', {
limit: parseInt($scope.getReactively('perPage'))*parseInt(($scope.getReactively('currentPage'))),
skip: 0,
sort: $scope.getReactively('model.sort'),
query: getQuery()
});
});
$scope.loadMore = function() {
// console.log('loading more');
$scope.currentPage += 1;
};
I'm not sure if I've used best practices with this answer, so please feel free to chime in with suggestions.

find out duplicate entry while editing the person name information in angular

I can create people information with their b'date using add button. It get displayed top of the page. If i want to edit information, I again click on that information and edit it easily. I need one validation there that i should not choose bday.name(person name) duplicate. e.q. if i already have "peter" person so i can't edit and change any other person name to "peter". so need to avoid duplicate entry in list.
plunker: http://plnkr.co/edit/2UFfaG?p=preview
$scope.newBirthday = function(){
$scope.bdays.push({name:$scope.bdayname, date:$scope.bdaydate});
$scope.bdayname = '';
$scope.bdaydate = '';
};
here is a simple solution using only angular js :
$scope.newBirthday = function(){
var exist=false;
angular.forEach($scope.bdays, function(bday) {
if(bday.name===$scope.bdayname){
exist=true;
bday.date=angular.copy($scope.bdaydate);
}
});
if(!exist){
$scope.bdays.push({name:$scope.bdayname, date:$scope.bdaydate});
}
$scope.bdayname = '';
$scope.bdaydate = '';
};

How to append a new value to an item within an array in Firebase?

Within Firebase, I have a list of 'ideas.' If a user presses a button associated with the idea, I'd like a value to be appended to that idea under an attribute called 'newValue.'
For example, the below html, uses ng-repeat to show the array of ideas and creates an associated button called 'Append Value.' I want a new value to be appended to the idea's attribute called 'newValue' every time a user presses 'Append Value.'
<body ng-controller="ctrl">
<table>
<tr class="item" ng-repeat="(id,item) in ideas">
<td>{{item.idea}}</td>
<td><input ng-model="newValue"></td>
<td><button ng-click="ValueAppend(id,newValue)">Append Value</button></td>
</tr>
</table>
</body>
Below is my attempt to create this function.
var app = angular.module("app", ["firebase"]);
app.factory("Ideas", ["$firebase", function($firebase) {
var Ref = new Firebase('https://crowdfluttr.firebaseio.com/');
var childRef = Ref.child('ideas');
return $firebase(childRef).$asArray();
}]);
app.controller("ctrl", ["$scope","Ideas", function($scope,Ideas) {
$scope.ideas = Ideas;
$scope.idea = "";
$scope.ValueAppend = function (id,newValue) {
var URL = "https://crowdfluttr.firebaseio.com/ideas/" + id + "newValue";
var IdeaRef = new Firebase(URL);
var IdeaData = $firebase(IdeaRef);
$scope.IdeaAttributes = IdeaData.$asArray();
$scope.IdeaAttributes.$add({
newValue: newValue,
timestamp: Date.now()
});
};
}]);
See my codepen for my working example: http://codepen.io/chriscruz/pen/PwZWKG
More Notes:
I understnad that AngularFire provides $add() and $save() to modify this array, but how could I use these methods so that I can add a new 'string' under an item in an array.
I'm not sure if these are your problems, but they are two typoes of mistakes in the code above and the codepen: typos and conceptual.
Typos
You forgot to inject $firebase into the controller, which leads to:
"ReferenceError: $firebase is not defined"
Solution is simply of course:
app.controller("ctrl", ["$scope","Ideas", "$firebase", function($scope,Ideas,$firebase) {
In addition you seem to be missing a slash before newValue, which means that you're trying to create a new idea instead of adding the value to an existing one. Solution is simple again, add a slash before newIdea as in:
var URL = "https://crowdfluttr.firebaseio.com/ideas/" + id + "/newValue";
If you find yourself making this mistake more often, you might be better server by the child function. Although it typically is a bit more code, it lends itself less to this typo of typo. Creating the ref to the newValue node becomes:
var URL = "https://crowdfluttr.firebaseio.com/ideas/";
var IdeaRef = new Firebase(URL).child(id).child("newValue");
Conceptual
With those trivial typos out of the way, we can focus on the real problem: which is easiest to see if you console.log the URL that you generate:
https://crowdfluttr.firebaseio.com/ideas/0/newValue
Yet if you look up the same data in the Firebase forge (by going to https://crowdfluttr.firebaseio.com/ideas/ in your browser), you'll see that the correct URL is:
https://crowdfluttr.firebaseio.com/ideas/-JbSSmv_rJufUKukdZ5c/newValue
That '0' that you're using comes from the id and it is the index of the idea in the AngularJS array. But it is not the key that Firebase uses for this idea. When AngularFire loads your data with $asArray it maps the Firebase keys to Angular indexes. We need to perform the reverse operation to write the new value to the idea: we need to map the array index (in id) back to the Firebase key. For that you can call [$keyAt(id)][1]. Since you keep the array of ideas in Ideas, it is simply:
var URL = "https://crowdfluttr.firebaseio.com/ideas/";
var IdeaRef = new Firebase(URL).child(Ideas.$keyAt(id)).child("newValue");
So the controller now becomes:
app.controller("ctrl", ["$scope","Ideas", function($scope,Ideas) {
$scope.ideas = Ideas;
$scope.idea = "";
$scope.ValueAppend = function (id,newValue) {
var URL = "https://crowdfluttr.firebaseio.com/ideas/";
var IdeaRef = new Firebase(URL).child(Ideas.$keyAt(id)).child("newValue");
var IdeaData = $firebase(IdeaRef);
$scope.IdeaAttributes = IdeaData.$asArray();
$scope.IdeaAttributes.$add({
newValue: newValue,
timestamp: Date.now()
});
};
}]);
I quickly gave it a spin in your codepen and this seems to work.

Resources