How can i prevent duplicate Record in Array - angularjs

I need to prevent inserting duplicate Rec in $scope.EmployeeList Array For that i wrote if ($scope.EmployeeList.indexOf(EmpDetails) == -1) but its not filtering my rec
$scope.EmployeeList = [];
var amtArray = [];
$scope.G_Total = "Total Amount is";
$scope.SaveDb = function (Isvalid) {
var EmpDetails = {
'EmpName': $scope.EmpName,
'Email': $scope.Email,
'Cost': $scope.cost
}
if ($scope.EmployeeList.indexOf(EmpDetails) == -1) {
$scope.EmployeeList.push(EmpDetails);
console.log($scope.EmployeeList);
}
else
alert('Duplicate Value....');

Don't use indexOf (it checks for strict equality), try findIndex:
if ($scope.EmployeeList.findIndex(function(e) { return e.EmpName === EmpDetails.EmpName; }) === -1) {
$scope.EmployeeList.push(EmpDetails);
console.log($scope.EmployeeList);
}

You can also use Array.prototype.some to find duplicate value.The some() method tests whether at least one element in the array passes the test implemented by the provided function.
var empDetails = {name: 'abc', email: 'a#gmail.com'};
let duplicate = $scope.EmployeeList.some(function (emp) {
return emp.name === empDetails.name && emp.email === empDetails.email;
});
if (!duplicate) {
$scope.EmployeeList.push(EmpDetails);
}
else
alert('Duplicate Value....');

Related

Protractor promises causing headaches when retrieving elements

Our web application has various html forms that each contain a list of form fields. Using Protractor, I'm looking for a way to retrieve the list of form fields: the field label, input type (textbox, select, radio, etc...), and input control (for setting the value later on). I then want to populate certain values for the fields in the form dynamically.
Here is the definition of the form field labels and the values I want to set:
this.fields = {
'Listing Agent': 1,
'Property Class': 1,
'Property Type': 2,
'Transaction Type': 'Sale',
'Ownership Terms': 'Sole Ownership',
'Listing Agreement': 'Yes',
'Display Listing on Internet': 'Yes',
'Display Address on Internet': 'Yes',
'Allow Automated Valuation on Internet': 'Yes',
'Allow Public Comment/Reviews on Internet': 'Yes'
};
I then retrieve the elements that match those field names by label text:
this.elements = form.find.allElements(this.fields);
When calling that method it retrieves the correct elements, but then I'm having trouble with setting the input type for each field. Checking the input type of a field returns a promise, not the actual value, so I can't figure out how to retrieve the input type for each element and then return an array of all of the elements.
this.find = {
allElements: function (fields) {
var items = [];
for (var key in fields) {
var el = element(by.cssContainingText('.sheet-grid-row', key));
this.getElementType(el).then(function (type) {
var item = {
type: type,
label: key,
isRequired: false,// TODO: el.getAttribute('class').indexOf('is-required-field') > -1
input: this.getElementInput(el, type)
};
items.push(item);
});
}
return items;// TODO: Doesn't work, of course...
},
getElementType: function (el) {
var deferred = protractor.promise.defer();
el.element(by.css('select')).isPresent().then(function (exists) {
if (exists)
deferred.fulfill(self.inputTypes.select);
else {
el.element(by.css('input[type="text"]')).isPresent().then(function (exists) {
if (exists)
deferred.fulfill(self.inputTypes.textbox);
else {
el.element(by.css('input[type="radio"]')).isPresent().then(function (exists) {
if (exists)
deferred.fulfill(self.inputTypes.textbox);
else
deferred.fulfill(self.inputTypes.unknown);
});
}
});
}
});
return deferred.promise;
},
getElementInput: function (el, type) {
switch (type) {
case self.inputTypes.select:
return new SelectWrapper(el.element(by.css('select')));
break;
case self.inputTypes.textbox:
return el.element(by.css('input[type="text"]'));
break;
case self.inputTypes.radio:
return el.element(by.css('input[type="radio"]'));
break;
}
return null;
}
};
At this point, I wish I could just get the native DOM elements and not deal with the promises at all. Is there a way to accomplish what I'm after?
You are trying to do asynchronous things element.isPresent() inside a synchronous loop for. You will want your allElements function to look more like this:
this.find = {
allElements: function (fields) {
var self = this;
var items = [];
var getItems = function(inputArray, currentIndex, outputArray) {
outputArray = outputArray || [];
currentIndex = currentIndex || 0;
var key = inputArray[currentIndex];
if (key) {
var el = element(by.cssContainingText('.sheet-grid-row', key));
return self.getElementType(el).then(function(type) {
var item = {
type: type,
label: key,
isRequired: false,// TODO: el.getAttribute('class').indexOf('is-required-field') > -1
input: self.getElementInput(el, type)
};
outputArray.push(item);
}).then(function() {
return getItems(inputArray, currentIndex + 1, outputArray);
});
} else {
return Promise.resolve(outputArray);
}
};
return getItems(Object.keys(fields));
},
getElementType: function (el) {
var self = this;
return el.element(by.css('select')).isPresent().then(function(exists) {
if (exists) {
return self.inputTypes.select;
} else {
return el.element(by.css('input[type="text"]')).isPresent().then(function(exists) {
if (exists) {
return self.inputTypes.textbox;
} else {
return el.element(by.css('input[type="radio"]')).isPresent().then(function(exists) {
if (exists) {
return self.inputTypes.radio;
} else {
return self.inputTypes.unknown;
}
});
}
});
}
});
},
getElementInput: function (el, type) {
switch (type) {
case self.inputTypes.select:
return new SelectWrapper(el.element(by.css('select')));
break;
case self.inputTypes.textbox:
return el.element(by.css('input[type="text"]'));
break;
case self.inputTypes.radio:
return el.element(by.css('input[type="radio"]'));
break;
}
return null;
}
};
Keep in mind that the output of find.allElements is now a promise, as it should be, so its usage will be something like:
this.find.allElements(this.fields).then(function(items) {
console.log('this is an array of my ' + items.length + ' items');
});

Can't compare MongoDB data with javascript array

I want to compare the data which I got from Mongo to javascript array. I am using lodash to compare. But it always return incorrect result.
var editUser = function(userData, getOutFunction) {
var status = CONSTANTS.NG;
checkExistUser(userData._id).then(function(user) {
if (user !== null) {
var userGroup = JSON.stringify(user.group);
user.group = user.group.map((groupId) => {
return groupId.toString();
});
var removedGroups = _.difference(userGroup, userData.group);
var addedGroups = _.difference(userData.group, userGroup);
console.log('Removed Groups: ', removedGroups);
console.log('Added Groups: ', addedGroups);
} else {
status = CONSTANTS.NG;
logger.debug(DEBUG_CLASS_NAME, "Cannot find object");
if (typeof(getOutFunction) !== 'undefined') {
getOutFunction(status, null);
} else {
NO_CALLBACK();
}
}
}).catch(function() {
console.log('Promise is error');
});
var checkExistUser = function(userId) {
return new Promise(function(resolve, reject) {
UserDAO.findById(userId, function(err, user) {
if (err) {
logger.debug(DEBUG_CLASS_NAME, {
name: err.name,
code: err.code,
message: err.message,
method: "checkExist"
});
resolve(null);
} else {
resolve(user);
}
});
});
}
For example:When I try to input value for lodash difference function
var user.group = ["58b8da67d585113517fed34e","58b8da6ed585113517fed34f"];
var userData.group = [ '58b8da67d585113517fed34e' ];
I want lodash difference return below result:
Removed Groups: ['58b8da6ed585113517fed34f']
Added Groups: []
However, the function gave me the result like:
Removed Groups: []
Added Groups: [ '58b8da67d585113517fed34e' ]
Can anyone help me in this case?
I will do appreciate it.
I have had this issue as well, the result from mongodb is an ObjectId type so you can compare the someObjectId.toString() value with your array of strings, or you could use
someObjectId.equals(stringOrObjectIdValue)
However, if you want to keep using lodash functions you will either have to force both arrays to strings or to ObjectIds before passing them into the function.

How to push a JSON object to an array in AngularJS

I need to push a JSON object to AngularJS and need to check before if the value for one of the objects exist. I need to overwrite the data.
$scope.setData = function(survey, choice) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
console.log(keepAllData);
toArray(keepAllData);
alert(JSON.stringify(toArray(keepAllData)));
$scope.keepAllDatas.push({
'surveyId': survey.id,
'choiceId': choice.id
});
var items = ($filter('filter')(keepAllDatas, {
surveyId: survey.id
}));
}
function toArray(obj) {
var result = [];
for (var prop in obj) {
var value = obj[prop];
console.log(prop);
if (typeof value === 'object') {
result.push(toArray(value));
console.log(result);
} else {
result.push(value);
console.log(result);
}
}
return result;
}
If the survey id exists in keepalldata, I need to change the recent value with choiceid. Is it possible to do with AngularJS?
Try with this: Before pushing data you have to check if the survey id exists or not. If it exists you have to update choice with the corresponding survey id, otherwise you can push directly.
$scope.setData = function(survey, choice) {
var item = $filter('filter')(keepAllData, {
surveyId: survey.id
});
if (!item.length) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
} else {
item[0].choiceId = choice.id;
}
console.log(keepAllData);
}
Demo
$scope.keepAllDatas = [];
$scope.setData = function(survey, choice) {
if($scope.keepAllDatas.length == 0) {
$scope.keepAllDatas.push({'surveyId':survey.id,'choiceId':choice.id});
}
else {
var items = ($filter('filter')( $scope.keepAllDatas, {surveyId: survey.id }));
for (var i = items.length - 1; i >= 0; i--) {
// alert(items[i].surveyId);
if(items[i].surveyId == survey.id) {
console.log($scope.keepAllDatas.indexOf(survey.id));
$scope.keepAllDatas.splice($scope.keepAllDatas.indexOf(survey.id),1);
console.log("Removed data")
}
}
$scope.keepAllDatas.push({'surveyId':survey.id, 'choiceId':choice.id});
console.log( $scope.keepAllDatas)
// alert(items[0].surveyId);
}
}

checkbox filter for json array in Angularjs

I have create a filter but this filter is not working with array inside array.
'http://plnkr.co/edit/oygy79j3xyoGJmiPHm4g?p=info'
Above plkr link is working demo.
app.filter('checkboxFilter', function($parse) {
var cache = { //create an cache in the closure
result: [],
checkboxData: {}
};
function prepareGroups(checkboxData) {
var groupedSelections = {};
Object.keys(checkboxData).forEach(function(prop) {
//console.log(prop);
if (!checkboxData[prop]) {
return;
} //no need to create a function
var ar = prop.split('=');
//console.log("ar is - "+ar);
if (ar[1] === 'true') {
ar[1] = true;
} //catch booleans
if (ar[1] === 'false') {
ar[1] = false;
} //catch booleans
/* replacing 0 with true for show all offers */
if(ar[0]=='SplOfferAvailable.text'){
ar[1]='true';
}else{
}
//make sure the selection is there!
groupedSelections[ar[0]] = groupedSelections[ar[0]] || [];
//at the value to the group.
groupedSelections[ar[0]].push(ar[1]);
});
return groupedSelections;
}
function prepareChecks(checkboxData) {
var groupedSelections = prepareGroups(checkboxData);
var checks = [];
//console.log(groupedSelections);
Object.keys(groupedSelections).forEach(function(group) {
//console.log("groupedSelections- "+groupedSelections);
//console.log("group- "+group);
var needToInclude = function(item) {
//console.log("item- "+item);
// use the angular parser to get the data for the comparson out.
var itemValue = $parse(group)(item);
var valueArr = groupedSelections[group];
//console.log("valueArr- "+valueArr);
function checkValue(value) { //helper function
return value == itemValue;
}
//check if one of the values is included.
return valueArr.some(checkValue);
};
checks.push(needToInclude); //store the function for later use
});
return checks;
}
return function(input, checkboxData, purgeCache) {
if (!purgeCache) { //can I return a previous 'run'?
// is the request the same as before, and is there an result already?
if (angular.equals(checkboxData, cache.checkboxData) && cache.result.length) {
return cache.result; //Done!
}
}
cache.checkboxData = angular.copy(checkboxData);
var result = []; // this holds the results
//prepare the checking functions just once.
var checks = prepareChecks(checkboxData);
input.every(function(item) {
if (checks.every(function(check) {
return check(item);
})) {
result.push(item);
}
return result.length < 10000000; //max out at 100 results!
});
cache.result = result; //store in chache
return result;
};
});
above code is for check box filter.
when i click on checkbox called "Availability" it does not filter the result.
Please help me out.
Thanks.
I think that the way you are navigating through json is wrong because if you put in this way it works
"Location": "Riyadh",
"AvlStatus": "AVAILABLE"
"Rooms": {.....
You have to go in some way through Rooms and right now I think you're not doing that

Nodejs async data duplication

I'm having some problems with one async process on nodejs.
I'm getting some data from a remote JSON and adding it in my array, this JSON have some duplicated values, and I need check if it already exists on my array before add it to avoid data duplication.
My problem is when I start the loop between the JSON values, the loop call the next value before the latest one be process be finished, so, my array is filled with duplicated data instead of maintain only one item per type.
Look my current code:
BookRegistration.prototype.process_new_books_list = function(data, callback) {
var i = 0,
self = this;
_.each(data, function(book) {
i++;
console.log('\n\n ------------------------------------------------------------ \n\n');
console.log('BOOK: ' + book.volumeInfo.title);
self.process_author(book, function() { console.log('in author'); });
console.log('\n\n ------------------------------------------------------------');
if(i == data.length) callback();
})
}
BookRegistration.prototype.process_author = function(book, callback) {
if(book.volumeInfo.authors) {
var author = { name: book.volumeInfo.authors[0].toLowerCase() };
if(!this.in_array(this.authors, author)) {
this.authors.push(author);
callback();
}
}
}
BookRegistration.prototype.in_array = function(list, obj) {
for(i in list) { if(list[i] === obj) return true; }
return false;
}
The result is:
[{name: author1 }, {name: author2}, {name: author1}]
And I need:
[{name: author1 }, {name: author2}]
UPDATED:
The solution suggested by #Zub works fine with arrays, but not with sequelize and mysql database.
When I try to save my authors list on the database, the data is duplicated, because the system started to save another array element before finish to save the last one.
What is the correct pattern on this case?
My code using database is:
BookRegistration.prototype.process_author = function(book, callback) {
if(book.volumeInfo.authors) {
var author = { name: book.volumeInfo.authors[0].toLowerCase() };
var self = this;
models.Author.count({ where: { name: book.volumeInfo.authors[0].toLowerCase() }}).success(function(count) {
if(count < 1) {
models.Author.create(author).success(function(author) {
console.log('SALVANDO AUTHOR');
self.process_publisher({ book:book, author:author }, callback);
});
} else {
models.Author.find({where: { name: book.volumeInfo.authors[0].toLowerCase() }}).success(function(author) {
console.log('FIND AUTHOR');
self.process_publisher({ book:book, author:author }, callback);
});
}
});
// if(!this.in_array(this.authors, 'name', author)) {
// this.authors.push(author);
// console.log('AQUI NO AUTHOR');
// this.process_publisher(book, callback);
// }
}
}
How can I avoid data duplication in an async process?
This is because you are comparing different objects and result is always false.
Just for experiment type in the console:
var obj1 = {a:1};
var obj2 = {a:1};
obj1 == obj2; //false
When comparing objects (as well as arrays) it only results true when obj1 links to obj2:
var obj1 = {a:1};
var obj2 = obj1;
obj1 == obj2; //true
Since you create new author objects in each process_author call you always get false when comparing.
In your case the solution would be to compare name property for each book:
BookRegistration.prototype.in_array = function(list, obj) {
for(i in list) { if(list[i].name === obj.name) return true; }
return false;
}
EDIT (related to your comment question):
I would rewrite process_new_books_list method as follows:
BookRegistration.prototype.process_new_books_list = function(data, callback) {
var i = 0,
self = this;
(function nextBook() {
var book = data[i];
if (!book) {
callback();
return;
}
self.process_author(book, function() {
i++;
nextBook();
});
})();
}
In this case next process_author is being called not immediately (like with _.each), but after callback is executed, so you have consequence in your program.
Not sure is this works though.
Sorry for my English, I'm not a native English speaker

Resources