Angularjs splice in loop - javascript

I am building this angularjs app, its my first one. So huge learning curve. I cant seem to to delete items as well as my search doesn't work. I managed to get column sorting and pagination to work though.
I get no errors so i am not sure why the search and deleting of item row in table isnt working.
I have tried using this:
$scope.remove = function(client){
for(var i = $scope.clients.length - 1; i >= 0; i--){
if($scope.clients[i].name == client.name){
$scope.clients.splice(i,1);
}
}
}
Working example: http://plnkr.co/edit/f2ozbP4JxrRSvRGJAmQi
ANSWER, WORKING:
Thanks #DTing
$scope.remove = function(client){
$scope.filteredItems = $scope.filteredItems.filter(function(item) {
return item.name !== client.name;
});
$scope.groupToPages();
}

This should be your remove function:
$scope.remove = function(client){
for(var i = $scope.pagedItems[$scope.currentPage].length - 1; i >= 0; i--){
if($scope.pagedItems[$scope.currentPage][i].name == client.name){
$scope.pagedItems[$scope.currentPage].splice(i,1);
break;
}
}
}
This should be your search function (note creation of $scope.clientsCopy):
$scope.clientsCopy = angular.copy(data);
$scope.searchMatch = function (haystack, needle) {
if (!needle) {
return true;
}
return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1;
};
// init the filtered items
$scope.search = function () {
$scope.filteredItems = $filter('filter')($scope.clientsCopy, function (item) {
for(var attr in item) {
if ($scope.searchMatch(item.name, $scope.query))
return true;
}
return false;
}
);
// take care of the sorting order
if ($scope.sortField !== '') {
$scope.filteredItems = $filter('orderBy')($scope.filteredItems, $scope.sortField, $scope.reverse);
}
$scope.currentPage = 0;
// now group by pages
$scope.groupToPages();
};
Plunker

You are trying to alter your $scope.clients which actually is empty because in your groupToPages function you set it to an empty array and repopulate or use it.
$scope.groupToPages = function () {
$scope.clients = [];
You can get it to work by removing items from your filteredItems array.
$scope.remove = function(client){
$scope.filteredItems.splice($scope.filteredItems.indexOf(client),1);
$scope.groupToPages();
}
http://plnkr.co/edit/z9NxW2FgYDlgLB20daO9?p=preview

Related

ng-repeat not updating properly in Angular js

I'm trying to put pagination with ng-repeat. Getting result but by the time showing old data and suddenly hide and show new set data, like jerking. My angularjs version is "1.5.8".
$scope.gap = 5;
$scope.filteredItems = [];
$scope.groupedItems = [];
$scope.itemsPerPage = 5;
$scope.pagedItems = [];
$scope.currentPage = 0;
var resultData = [...];
var searchMatch = function (haystack, needle) {
if (!needle) {
return true;
}
return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1;
};
// init the filtered items
$scope.search = function () {
$scope.filteredItems = $filter('filter')(resultData, function (item) {
for(var attr in item) {
if (searchMatch(item[attr], $scope.query))
return true;
}
return false;
});
// take care of the sorting order
$scope.currentPage = 0;
// now group by pages
$scope.groupToPages();
};
$scope.groupToPages = function () {
$scope.pagedItems = [];
for (var i = 0; i < $scope.filteredItems.length; i++) {
if (i % $scope.itemsPerPage === 0) {
$scope.pagedItems[Math.floor(i / $scope.itemsPerPage)] = [ $scope.filteredItems[i] ];
} else {
$scope.pagedItems[Math.floor(i / $scope.itemsPerPage)].push($scope.filteredItems[i]);
}
}
console.log($scope.pagedItems)
};
$scope.range = function (size,start, end) {
var ret = [];
//console.log(size,start, end);
if (size < end) {
end = size;
start = size-$scope.gap;
}
for (var i = start; i < end; i++) {
ret.push(i);
}
// console.log(ret);
return ret;
};
$scope.prevPage = function () {
if ($scope.currentPage > 0) {
$scope.currentPage--;
}
};
$scope.nextPage = function () {
if ($scope.currentPage < $scope.pagedItems.length - 1) {
$scope.currentPage++;
}
};
$scope.setPage = function () {
console.log($scope.pagedItems[$scope.currentPage]);
$scope.currentPage = this.n;
};
$scope.search();
html
<tr ng-repeat="user in pagedItems[currentPage]" >
<td>{{user.name}} {{$index}}</td>
</tr>
As above code, that table row update as 5 row. but when I click next or page numbers showing 10 rows and hide 5 rows. I hope you understand guys! Help me.
In my opinion you are thinking wrong, it's simpler to use custom filter and break up your business logic like this
app.filter('startFrom', function() {
return function(input, start) {
start = +start;
return input.slice(start);
}
});
then in the controller you can do
$scope.showResults = function() {
$scope.list = $filter('startFrom')($scope.initialList, $scope.page * $scope.itemsPerPage);
$scope.list = $filter('limitTo')($scope.list, $scope.itemsPerPage);
}
};
now you need only to update $scope.page and reuse $scope.showResults() to update the view
<tr ng-repeat="user in list" >
<td>{{user.name}} {{$index}}</td>
</tr>
I don't think that your problem is cause by ng-repeat. I just take your code, add some dummy data and do a test and it's totally work fine.
You can check it here https://codepen.io/Cushdrive/pen/zvPPXd
Because angular is two way binding, so I'm wonder that could it be some paging info was triggered somewhere. Could you double check on some variable like currentPage itemPerPages or pagedItems to see if it being used somewhere else?

Pagination in Angular.js

I am trying to add pagination in Angular js.Sinch my server returns huge number of rows on each query So i am using some limit offset to get only 101 rows(required rows+1) at a time.(Building array of 20 pages ,reusing extra row value for next request.)
No- of rows per page=5
So on getting 101 rows means i can paginate upto 20 pages. Since i already have an extra row So i know there is more data left , So on next page request again am querying to get rows 101-201. But my doubt here is how to add logic in next page and previous page function and how to build next or previous set of data?
My app.js-
My 1st time request-
$scope.startingid = null;
$scope.numberofrows= 101;
Api.customer.query({ productId : $scope.customer , productperiod :$scope.customerPeriod,startingid:$scope.startingid,numberofrows:$scope.numberofrows }).$promise.then(function(result) {
if(result){
if(result&&result.length==0){
$scope.addErrorAlert("No Customer data found with this productId and Period.", true);
$scope.displayPage = 'search';
return;
}
$scope.customerResult = result;
$scope.displayPage = 'drill';
$scope.showData();
}
// Pagination Logic-
My code is working fine if result set is small number of data. But need to implement in such a way that it can handle large number of rows as well.
few doubts-
1. how to build the data for request 101-201.
2. next and previous page logic
$scope.paged = function (valLists,itemsPerPage)
{
var retVal = [];
for (var i = 0; i < valLists.length; i++) {
if (i % itemsPerPage === 0) {
retVal[Math.floor(i / itemsPerPage)] = [valLists[i]];
} else {
retVal[Math.floor(i / itemsPerPage)].push(valLists[i]);
}
}
return retVal;
};
$scope.pagination = function () {
$scope.ItemsByPage = $scope.paged( $scope.customerResult, $scope.itemsPerPage );
};
$scope.showData = function( ){
// $scope.noOfrows = 101;
$scope.itemsPerPage = 5;
$scope.currentPage = 0;
$scope.pagination();
$scope.range = function() {
var rangeSize = 4;
var ps = [];
var start;
start = $scope.currentPage;
if ( start > $scope.pageCount()-rangeSize ) {
start = $scope.pageCount()-rangeSize+1;
}
for (var i=start; i<start+rangeSize; i++) {
ps.push(i);
}
return ps;
};
$scope.prevPage = function() {
if ($scope.currentPage > 0) {
$scope.currentPage--;
}
};
$scope.DisablePrevPage = function() {
return $scope.currentPage === 0 ? "disabled" : "";
//?? TODO add logic for samething as disabled next page and build table data
};
$scope.pageCount = function() {
return Math.ceil($scope.customerResult.length/$scope.itemsPerPage)-1;
};
$scope.nextPage = function() {
if ($scope.currentPage < $scope.pageCount()) {
$scope.currentPage++;
}
};
$scope.DisableNextPage = function() {
if($scope.currentPage === $scope.pageCount()){
if($scope.noOfrows >$scope.customerResult.length)
return $scope.currentPage === $scope.pageCount() ? "disabled" : "";
$scope.noOfrows = $scope.noOfrows+ 100;
Api.customerReq.query({ productId : $scope.customerProduct , productperiod :$scope.customerPeriod, noOfrows:$scope.noOfrows }).$promise.then(function(result) {
if(result){
if(result&&result.length==0){
return $scope.currentPage === $scope.pageCount() ? "disabled" : "";
}
$scope.showData();// how to build all data on when i query for 101-201 data?
}
});
}
};
$scope.setPage = function(n) {
$scope.currentPage = n;
};
};

Recursive function to traverse grid goes crazy

When the user clicks on one of the blocks in the table ( see screenshot ) I want to find all neighbouring blocks with the same color. I am trying to do this recursively, but if I try it with more than three blocks it sometimes goes crazy and calls itself over and over until the program crashes.
As far as I can see, the objects are added to the array, but somehow my tests fails and the same object is added over and over and over.
Any insight on what the problem might be and how to solve it would be much appriciated!
Here's a screenshot
This is the function that is called when the user clicks on a block:
var $matchArray;
$('.block').click(function () {
$matchArray = [$(this)];
var $colorClass;
if ($(this).hasClass('red')) {
$colorClass = 'red';
} else if ($(this).hasClass('green')) {
$colorClass = 'green';
} else if ($(this).hasClass('blue')) {
$colorClass = 'blue';
} else {
$colorClass = 'error';
}
findAllSameColorNeighbours($(this), $colorClass);
});
And this is the recursive method:
findAllSameColorNeighbours = function ($this, $colorClass) {
$this.css('border-style', 'solid');
//LEFT
var $leftBlock = isLeftBlockSameColor($this, $colorClass);
if ($leftBlock != null) {
if (!(arrayContains($matchArray, $leftBlock))) {
$matchArray.push($leftBlock);
findAllSameColorNeighbours($leftBlock, $colorClass);
}
}
//ABOVE
//same as for LEFT
//RIGHT
//same as for LEFT
//BELOW
//same as for LEFT
}
This is how I find the neighboring cells, as far as I can see these work just fine. I have one for each direction:
isLeftBlockSameColor = function ($block, $color) {
var $this = $block;
var $tr = $this.parent().parent();
var col = $tr.children().index($this.parent().prev());
var $leftBlock = $this.parent().siblings().eq(col).children();
var $blockClassMatch = $leftBlock.hasClass($color);
if ($blockClassMatch) {
return $leftBlock;
}
else {
return null;
}
};
Here are some help methods to find out if the object is already in the array or not. I use the index of the row and cell to create a sort of latitude and longditude thing.
arrayContains = function ($array, $object) {
for (i = 0; i < Array.length; i++) {
if (compareIndex($array[i], $object)) {
say('true');
return true;
}
};
return false;
};
compareIndex = function ($obj1, $obj2) {
if ((getRowIndex($obj1)) === (getRowIndex($obj2)) {
if ((getCellIndex($obj1)) === (getCellIndex($obj2)) {
return true;
} else {
return false;
}
} else {
return false;
}
};
getCellIndex = function ($this) {
var $tr = $this.parent().parent();
var index = $tr.children().index($this.parent());
return index;
};
getRowIndex = function ($this) {
var $tr = $this.parent().parent();
var index = $tr.index();
return index;
};
There is a bug in the arrayContains function. The loop will iterates only once, because Array.length is equals to 1(As I tested with chrome browser, but I don't know why). You should use $array.length instead.
arrayContains = function ($array, $object) {
//for (i = 0; i < Array.length; i++) {
for (i = 0; i < $array.length; i++) {
if (compareIndex($array[i], $object)) {
say('true');
return true;
}
};
return false;
};

JavaScript: Can this code be refactored to a more functional programming style?

Can this code be chained and the for loop abstracted away? Using map and filter?
function listViewFilter(){ // test
var DateFiltered = containerdata.filter(function (obj){ // remove dates of 010
return !/010/.test(obj.EventDate);
});
var NameFiltered = [];
for (var i = 0; i < DateFiltered.length; i++){ // remove EventNames.Name if empty string
if (DateFiltered[i].EventNames[0].Name == "") continue;
else NameFiltered.push(DateFiltered[i]);
}
Filtered = NameFiltered;
}
Sure, your for loop does nothing but another filter:
function listViewFilter() {
var DateFiltered = containerdata.filter(function(obj) { // remove dates of 010
return !/010/.test(obj.EventDate);
});
var NameFiltered = DateFiltered.filter(function(obj, i) { // remove EventNames.Name if empty string
return obj.EventNames[0].Name != "";
});
Filtered = NameFiltered;
}
or in short
function listViewFilter() {
Filtered = containerdata.filter(function(obj) {
return !/010/.test(obj.EventDate) && obj.EventNames[0].Name != "";
});
}

Angularjs filtering json results

I'm having trouble filtering a json object using a filter function from a repeater. The filter was working on the first level without issue but now when I try to filter the rest of the collection and then return the scope data if the filter is not defined I get errors.
I've created a fiddle, I appreciate the help.
app.filter('showByfilValue',['ctrl'], function ($scope,ctrl) {
return function (items, word) {
var filtered = [];
if (typeof word !== 'undefined') {
var letterMatch = new RegExp('^' + word + '$', 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (letterMatch.test(item.services[0].services[0].serviceName)) {
filtered.push(item);
}
}
return filtered;
} else {
return data;
}
};
});
Jimi

Categories