I have a set of radio buttons, when a radio button is selected the element is pushed into an object.
Then I need to take the value of the elements in the object and then push them into an array, if they are not already in the array.
My problem is that I keep getting duplicates or more in my array of each of the values with this function because I am not checking correctly if they exists.
How can I check if the element already exists in my array and then exclude it from being added?
_this.selected = {};
_this.selectedArray = [];
//loop through the object
angular.forEach(_this.selected, function ( item ){
//if it is not the first time the array is getting data loop through the array
if(_this.selectedArray.length > 0) {
_this.selectedArray.forEach(function (node){
//check to see if the item already exists-- this is where it is failing
//and running the loop too many times
if(node.id !== item.id){
_this.selectedArray.push(item);
}
});
} else {
_this.selectedArray.push(share);
}
});
You can use additional hash to check if you have already added item to array.
_this.selected = {};
_this.selectedArray = [];
_this.selectedHash = {};
//loop through the object
angular.forEach(_this.selected, function ( item ){
if(_this.selectedHash[item.id]) { return; }
_this.selectedArray.push(item);
_this.selectedHash[item.id] = 1;
});
Have you tried jQuery's inArray? http://api.jquery.com/jquery.inarray
It works the same as the indexOf method on String.
You could try if $.inArray(node, selectedArray) == -1 // element is not in the array
You can run this function on that array to reduce it to unique values rather than applying complex code to check whether the array had an element or not
var getOnlyUniqueValuesInArray = function(arrayObj) {
return arrayObj.reduce(function(a, b) {
if (a.indexOf(b) < 0) a.push(b);
return p;
}, []);
};
Hi that should helps
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope){
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope) {
_this.selected = {};
_this.selectedArray = [];
//loop through the object
angular.forEach(_this.selected, function(item) {
//if it is not the first time the array is getting data loop through the array
if (_this.selectedArray.length > 0) {
var canAdd = true;
_this.selectedArray.forEach(function(node) {
//do not add iny any of node.id will be equal to item.id
if (node.id == item.id) {
canAdd = false;
}
});
if(canAdd){
_this.selectedArray.push(item);
};
} else {
_this.selectedArray.push(share);
}
});
})
});
Related
Can someone explain me this strange js behavior ?
All of this is in AngularJS.
I have helper function in my main app.js to simply return element from an array by its id:
var MyLib = MyLib || {};
MyLib.helpers = {
find: function(needle, stack) {
for (var i = 0; i < stack.length; i++) {
if(stack[i]._id === needle)
return stack[i];
}
return false;
}
}
Then I have factory and function to handle database change:
// categories are grabbed from db
var categories = [some array of objects];
// change is object returned from database that has all info about object as well as new object itself
function handleChange(change) {
var _category = MyLib.helpers.find(change.id, categories);
// if deleted, that part is ok
if(change.deleted) {
var idx = categories.indexOf(_category);
if(idx !== -1) {
categories.splice(idx, 1);
}
} else {
// if updated that part is weird
if(_category) {
_category = change.doc;
}
// if newly added that part is ok
else {
categories.push( angular.copy(change.doc) );
}
}
}
Why when I try to update element grabbed from categories array doesn't update in categories array ?
// categories ARE NOT updated after this
_category = change.doc;
and only when I refer to categories by index like this:
// categories ARE updated after this although _category is returned from this array by index (find function)
var idx = categories.indexOf(_category);
categories[idx] = change.doc;
I don't understand this...
You are overwriting the variable with a new value and any reference to prior value is gone.
Instead of overwriting the original object value with a new object you could update the existing object using angular.extend()
angular.extend(_category, change.doc);
I didn't analyze everything, but you should always have dot notation.
_category pass by value, and will not change when 'MyLib.hel ...' is changed
var _category = MyLib.helpers.find(change.id, categories);
something.category pass by reference, and will be changed when 'MyLib.hel ...' is changed
var something.category = MyLib.helpers.find(change.id, categories);
I have one array i want to iterate that in the iteration process we check one condition if condition is true we return one value otherwise we return else part I write some code but its not working.
the loop will not terminated if condition is true how can i do that cam anyone help me?
$scope.bgImages = []; //it having some objects
$scope.job = []; //it also having some objeccts
//if both elements are matching we return one value
$scope.getJobDepartmentImg = function() {
var jobDepartment = $scope.job.department;
for (var i in $scope.bgImages) {
var department = $scope.bgImages[i].departmentName;
var job_header = $scope.bgImages[i].s3ImageUrl;
if (jobDepartment === department) {
return job_header;
} else {
return default_job_header;
}
}
};
The loop is not terminated if condition is satisfiedd that method will continiouslyy can anyone help me?
put an second return outside else statement
$scope.getJobDepartmentImg = function() {
var jobDepartment = $scope.job.department;
for (var i in $scope.bgImages) {
var department = $scope.bgImages[i].departmentName;
var job_header = $scope.bgImages[i].s3ImageUrl;
if(jobDepartment === department){
return job_header;
}
}
return default_job_header;
}
it will iterate through array and return job_header if it finds one, or return default if loop ends
Currently my code looks like this:
var arrayListEnum = list.getEnumerator();
while (arrayListEnum.moveNext()) {
var listItem = arrayListEnum.get_current();
if (listItem.get_id() == id) {
//stuff(listItem);
break;
}
}
Maybe I'm just spoiled by C#, but I don't really like the look of this. In JavaScript or jQuery (I'd rather not include an entire other library), is there a way for me to do something like:
var item = (from items in list.getEnumerator()
where items.get_id() == id
select items);
//stuff(item);
or
var item = list.getEnumerator().Where(item => item.get_id() == id);
//stuff(item);
Thanks in advance.
I guess you are getting list item collection from list, in that case if you interested only in getting list item by its id, then i would suggest utilize SP.List.getItemById Method, for example:
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
var item = list.getItemById(itemId);
ctx.load(item);
ctx.executeQueryAsync(
function() {
console.log(item.get_id());
},
function(sender,args){
console.log(args.get_message());
});
Note: from performance perspective the advantage here that there is no
need to request list item collection and then filter item on the
client side
Below are provided some examples that demonstrate how to find/filter list item in collection by property
1) Using getEnumerator method
function findListItem(items,propertyName,propertyValue)
{
var e = items.getEnumerator();
while (e.moveNext()) {
var listItem = e.get_current();
if (listItem.get_item(propertyName) == propertyValue) {
return listItem
}
}
return null;
}
2) Using for statement
function findListItem(items,propertyName,propertyValue)
{
for(var i = 0; i < items.get_count();i++) {
var listItem = items.get_item(i);
if (listItem.get_item(propertyName) == propertyValue) {
return listItem
}
}
return null;
}
3)Using filter() method:
//returns array(!)
function findListItem(items,propertyName,propertyValue)
{
return items.get_data().filter(function(item){
if (item.get_item(propertyName) == propertyValue) {
return item
}
});
}
If your collection is in an array, you can kind-of use Array.filter.
var array = [1, 2, 3, 4, 5];
var item = array.filter(function (element) {
return element === 3;
})[0];
console.log(item); // 3
This will put the result in item and leave the original array untouched.
There's the caveat that Array.filter returns an array, not a single element. In your case you want a single element, hence [0] at the end of the function call.
For browsers which do not implement Array.filter the MDN page has a polyfill.
Quick edit/addition: Another caveat is that this walks through the whole collection, even after the matching element is found.
This could be something simple and I'm overlooking it. But I'm building out a filter by categories and once a user clicks a category it updates a scope (my instance $scope.productStuff) and display the objects accordingly. My problem is when I click the category it gives me back the mulitple objects in my console. Then I look at the dom and it only shows one object (and it's the last object) instead all the objects that are in my console.
Here is my function:
$scope.update = function(val) {
angular.forEach($scope.productStuff, function(item){
if( item.s2 === val.toUpperCase()){
$scope.productStuff = [item];
}
});
}
Here is my factory that's getting the data on page load
dataFactory.getProducts().then(function(res){
$scope.productStuff = res.data;
$scope.loading = false;
});
So my question is why is it displaying one object in the dom and multiple objects in the console and how do I put the items on the $scope.productStuff?
$scope.update = function(val) {
// Create an empty array
var stuff = [];
angular.forEach($scope.productStuff, function(item){
if( item.s2 === val.toUpperCase() ){
// push to our array when condition is met (filter)
stuff.push(item);
}
});
// $scope.productStuff now contains all the filtered items
$scope.productStuff = stuff;
}
You are trying to modify iterate over and modifying $scope.productStuff too. As soon as you write:
$scope.productStuff = [item];
only one item remains in it. try creating a new array and once done assign it to $scope.productStuff
$scope.update = function(val) {
var tempArray = [];
angular.forEach($scope.productStuff, function(item){
if( item.s2 === val.toUpperCase()){
tempArray.push(item);
}
});
$scope.productStuff = tempArray;
}
I have a small Angular app that I'm writing that makes use of Underscore to look over each object in an array, and remove the object if it does not match the keyword (user input).
$scope.search = function() {
$scope.posts = _.reject($scope.posts, function(p) {
var i = 0;
if ($scope.keywords.indexOf(p.author) < 0 ) {
i++;
}
if ($scope.keywords.indexOf(p.id) < 0 ) {
i++;
}
if(i > 0) {
return true;
}
});
};
As you can see I'm setting a counter, and then adding to the counter if the keyword is found in the index, then at the end checking the counter to return true or false to remove the object from the array. $scope.posts is array of objects with my data and $scope.keywords is the user input. I'm wanting to lookup the input from $scope.posts.author object and $scope.posts.id object.
If I remove one of the if statements the function performs as expected: everything not matching the keyword is removed from the array. However, as soon as I add another if statement to the function (as seen in my example above), ALL objects are removed from the array.
It looks to me as though filter might be a better fit here:
$scope.posts = _.filter($scope.posts, function(p) {
return $scope.keywords.indexOf(p.author) > -1 || $scope.keywords.indexOf(p.id) > -1;
});
Working example: http://jsfiddle.net/4xp3sm10/
Instead of filter or reject it would be even easier to do it the opposite way using _.where
var newArray = _.where($scope.posts, {keyword : $scope.keyword});
There you go, one line.
Edit:
If you are stuck on doing it this way, here's a way you could clean it up a little.
$scope.posts = _.reject($scope.posts, function(p) {
var check = false;
if ($scope.keywords.indexOf(p.author) < 0 ) {
check = true;
}
if ($scope.keywords.indexOf(p.id) < 0 ) {
check = true;
}
if(i > 0) {
return check;
}
});
};
No need to use an integer like that
Since you are rejecting rows you will want to make sure ALL conditions are true. Your code is just checking for either one to be true.
$scope.search = function() {
$scope.posts = _.reject($scope.posts, function(p) {
return (
($scope.keywords.indexOf(p.author) < 0 ) &&
($scope.keywords.indexOf(p.id) < 0 )
);
});
};