I am trying to use the splice() function in Angular JS. I have a dropdown from which users can select an item.
The selected item has a field and a value which gets parsed into the array ‘criteria’.
The user then clicks another item on the same drop down, and I want to make sure it checks to see if the field already exists. If it does, the code should remove the existing field and insert the new one.
There should only ever be one field name in this array.
Please note I have other drop down lists using the same criteria array so these should not be effected.
Example drop down list contains:
0 * 1 Apple 2 Pear 3 Orange
Currently if you click Apple, the criteria array populates correctly.
Field: TypeName, Value: Apple
The second time you click on the SAME drop down, the Orange criteria array populates as follows:
Field: TypeName, Value: Apple Field: TypeName, Value: Orange
I need the code to remove the original click item, as the field TypeName already exists in the array; e.g. the value Apple and Push/Replace with Orange into the criteria array
HTML – example drop down code that calls ng-click filterData function:
<span class="input-group-btn"> <div class="dropdown"> <button class="btn btn-error dropdown-toggle" type="button" data-toggle="dropdown" ng-bind="selected"> Select Type <span class="caret"></span> </button> <ul class="dropdown-menu"> <li class="list-group-item-{{item.type}}" ng-repeat="item in types"> <a href="#" ng-click="filterData('TypeName',item.type); setType(item.type)">{{item.type}}</a > </li> </ul> </div> </span>
Array.prototype.flexFilter = function(info) { // Set our variables var matchesFilter, matches = [], count; // Helper function to loop through the filter criteria to find matching values // Each filter criteria is treated as "AND". So each item must match all the filter criteria to be considered a match. // Multiple filter values in a filter field are treated as "OR" i.e. ["Blue", "Green"] will yield items matching a value of Blue OR Green. matchesFilter = function(item) { count = 0 for (var n = 0; n < info.length; n++) { if (info[n]["Values"].indexOf(item[info[n]["Field"]]) > -1) { count++; } } // If TRUE, then the current item in the array meets all the filter criteria return count == info.length; } console.log("length ", this.length); // Loop through each item in the array for (var i = 0; i < this.length; i++) { // Determine if the current item matches the filter criteria if (matchesFilter(this[i])) { matches.push(this[i]); } } console.log("matches log ", matches); // Give us a new array containing the objects matching the filter criteria return matches; } //Add this next to your functions var criteria = []; $scope.filterData = function filterData(field, value) { var index = criteria.map(function(e) { return e.field; }).indexOf(field); console.log(index); if (index > -1 || value == "*") //ISSUE IS HERE { criteria.splice(index, 1); } else { criteria.push({ Field:field, Values: [value] }); console.log(criteria); } let newData = $scope.dummyData.flexFilter(criteria); $scope.getData(newData); }
The first time I click the item my index is -1.
The second time I click an item my index seems to still be -1.
Console log output:
(2) [{…}, {…}] 0: {Field: "TypeName", Values: Array(1)} 1: {Field: "TypeName", Values: Array(1)} length: 2
Advertisement
Answer
The question is not very clear but looking at your expected output I think the mistake is in line
var index = criteria.map(function(e) { return e.field; }).indexOf(field);
e.field should be e.Field. So, correct statement is:
var index = criteria.map(function(e) { return e.Field; }).indexOf(field);
further do not push to criteria inside else. Based on your expected output you always want to push. You just want to remove if anything is already there before pushing.
$scope.filterData = function filterData(field, value) { var index = criteria.map(function (e) { return e.Field; }).indexOf(field) console.log(index); if (index > -1 || value == "*") //ISSUE IS HERE { criteria.splice(index, 1); } criteria.push({ Field: field, Values: [value] }); console.log(criteria); let newData = $scope.dummyData.flexFilter(criteria); $scope.getData(newData); }