How to Use Conditionals in JS Find Function - javascript

I'm wondering how to use an if statement in the JS find function? My goal here is when these values do not match to addClass("filtered-out") to the elements in my cars array.
cars.map(car => active_filters.find(x =>
if (car.attr(x.id) !== x.value)
return car.addClass("filtered-out");
));

I don't know logic you coded is true or not, but you can use simple loop and check condition.
cars.forEach(function(car) {
for (var i = 0; i < active_filters.length; i ++) {
if (car.attr(active_filters[i]['id']) !== active_filters[i]['value']) {
car.addClass("filtered-out");
break;
}
}
});
Or something like this
cars.forEach(function(car) {
var found = active_filters.find(function(el) {
return car.attr(el['id']) === el['value'];
});
if (!found) {
car.addClass("filtered-out");
}
});

Related

javascript reusable function

people, I have a question. I have two javascript functions that do the same thing. Note that it only changes the "let selected" variable. I don't think it's the best way to use functions in js, how can I reuse them?
First function:
onChange(id) {
let selected = this.state.selectedDevice
let find = selected.indexOf(id)
if(find > -1) {
selected.splice(find, 1)
} else {
selected.push(id)
}
this.setState({ selected })
}
Second function:
onChangeSec(id) {
let selected = this.state.selectedSection
let find = selected.indexOf(id)
if(find > -1) {
selected.splice(find, 1)
} else {
selected.push(id)
}
this.setState({ selected })
}
thanks !!!
You could just pass key as another function parameter
onChange(id, key) {
let selected = this.state[key]
let find = selected.indexOf(id)
if(find > -1) {
selected.splice(find, 1)
} else {
selected.push(id)
}
this.setState({ selected })
}
and in your case key would be 'selectedDevice' or 'selectedSection' passed as a string.
It seems like this.state.selectedDevice and this.state.selectedSection are both arrays, and since you're using index-based retrieval from the array, there's no way from within the function to determine which should be used. Instead you should pass that information into the function. For example:
onChange(id, data) {
const position = data.indexOf(id)
this.setState({
selected: position > -1
? [...data.slice(0, position), ...data.slice(position + 1)]
: [...data, 1]
})
}
Note: this also works around your mutation of an object in state, which will cause bugs.
You might also want to consider using a Set instead:
constructor() {
this.state = {
selected: new Set()
}
}
onChange(value) {
const newSelected = new Set(this.state.selected)
if (newSelected.has(value)) {
newSelected.delete(value)
} else {
newSelected.add(value)
}
this.setState({ selected: newSelected })
}
This is safer than an array where you can have multiple entries of the same value.

How to return multiple functions dynamically Javascript

I apologize if I didn't ask my question in the correct way. Let me explain my problem.
I'm working on a search function in a table, I'm adding the option to search in specific columns.
Right now I'm manually checking if the checkboxes are selected or not, then return the proper search function.
However I want to make it dynamically, I don't want to edit this code after every time I add new columns to the table. That's where I'm struggling.
This is my current code:
vm.$watch('searchTerm', function (searchTerm) {
if (!searchTerm) {
vm.filteredTable = angular.copy(vm.table);
} else {
searchTerm = searchTerm.toLowerCase();
return vm.filteredTable.rows = vm.table.rows.filter(function (row) {
if (vm.searchFilter[0] === true ){
return (contains(row[vm.table.columns[0].value], searchTerm))
}
if (vm.searchFilter[1] === true ){
return (contains(row[vm.table.columns[1].value], searchTerm))
}
if (vm.searchFilter[2] === true ){
return (contains(row[vm.table.columns[2].value], searchTerm))
}
if (vm.searchFilter[3] === true ){
return (contains(row[vm.table.columns[3].value], searchTerm))
}
if (vm.searchFilter[4] === true ){
return (contains(row[vm.table.columns[4].value], searchTerm))
}
if (vm.searchFilter[5] === true ){
return (contains(row[vm.table.columns[5].value], searchTerm))
}
if (vm.searchFilter[6] === true ){
return (contains(row[vm.table.columns[6].value], searchTerm))
}
if (vm.searchFilter[7] === true ){
return (contains(row[vm.table.columns[7].value], searchTerm))
}
});
}
});
This is the way I created it, I tried to use a loop, but I can't return the functions if there is a loop. Also adding return before the for loop wont help either.
vm.$watch('searchTerm', function (searchTerm) {
if (!searchTerm) {
vm.filteredTable = angular.copy(vm.table);
} else {
searchTerm = searchTerm.toLowerCase();
return vm.filteredTable.rows = vm.table.rows.filter(function (row) {
for (let i=0; i<vm.searchFilter.length; i++){
if (vm.searchFilter[i] === true ){
return (contains(row[vm.table.columns[i].value], searchTerm))
}
}
});
}
});
This is probably a very easy case for the most of you, so I apologize if I'm just being stupid right now. I'm working since 2 hours on this till now...
EDIT:
The function I mean:
const contains = (value, searchTerm) => {
if (!value) return false;
return value.toLowerCase().includes(searchTerm);
}
2nd EDIT:
I just realized after a kind member told me that, that the first version isnt working either the way I want it.
There is the option to have a multiple selection, so if I select the first two checkboxes, then it should search in BOTH of them and not only one.
You can just iterate over the whole thing like this:
vm.$watch('searchTerm', function (searchTerm) {
if (!searchTerm) {
vm.filteredTable = angular.copy(vm.table);
} else {
searchTerm = searchTerm.toLowerCase();
return vm.filteredTable.rows = vm.table.rows.filter(row =>
vm.searchFilter.some((filter, index) => filter && contains(row[vm.table.columns[index].value])))
}
By using Array.prototype.some you essentially ask whether your row matches at least one of the filters.

Array objects difference javascript angularjs

I have 2 array objects and I want to get the difference between them as follows:
array1 = [{"name":"MPCC","id":"tool:mpcc"}, {"name":"APP","id":"tool:app"}, {"name":"AII","id":"tool:aii"}, {"name":"VZZ","id":"tool:vzz"}, {"name":"USU","id":"tool:usu"}]
array2 = [{"name":"APP","id":"tool:app"}, {"name":"USU","id":"tool:usu"}]
result = [{"name":"MPCC","id":"tool:mpcc"}, {"name":"AII","id":"tool:aii"}, {"name":"VZZ","id":"tool:vzz"}]
Here is the code:
$scope.initial = function(base, userData){
var result = [];
angular.forEach( base, function(baseItem) {
angular.forEach( userData, function( userItem ) {
if ( baseItem.id !== userItem.id ) {
if (result.indexOf(baseItem) < 0) {
result.push(baseItem);
}
}
});
});
return result;
}
$scope.initial(array1, array2);
The problem with the above code is I dont get the desired result. Please let me know what is going wrong.
That is not related to Angular.
You could do something like this:
var result = array1.filter(function(item1) {
for (var i in array2) {
if (item1.id === array2[i].id) { return false; }
};
return true;
});
Or with ES6 syntax:
var result = array1.filter(i1 => !array2.some(i2 => i1.id === i2.id));
I think this is not related to Angular itself. You're looking for an algorithm to compute a difference between 2 sets.
The topic has already been discussed. You may also be interested on this underscore plugin

Check if a JSON array is empty

I know from the first look it sounds like duplicate question but i don't think it is...
I am receiving back a JSON array as:
var test1 = [] ;
or
var test2 = [{},{},{}] ; //This is empty
I have no problem finding out if test1 is empty.
jQuery.isEmptyObject(test1)
My problem is with the test2...
Please note that in some cases the test2 might return something like:
var test2 = [{"a":1},{},{}] ; //All these are not empty
var test2 = [{},{"a":1},{}] ; //All these are not empty
var test2 = [{},{},{"a":1}] ; //All these are not empty
The above scenarios shouldn't be counted as empty.I've tried to use .length but it's not helping as the length is always 3... Any ideas?
Cheers.
function isArrayEmpty(array) {
return array.filter(function(el) {
return !jQuery.isEmptyObject(el);
}).length === 0;
}
jsFiddle Demo
Passes all of your tests.
A pure JavaScript solution would be to replace !jQuery.isEmptyObject(el) with Object.keys(el).length !== 0
Edit: Using Array.prototype.every
function isArrayEmpty(array) {
return array.every(function(el) {
return jQuery.isEmptyObject(el);
});
}
For those playing at home, a non jQuery solution:
var test2 = [{a: 1},{},{}] ; //This is empty
function isEmpty(val) {
var len = val.length,
i;
if (len > 0) {
for (i = 0; i < len; ++i) {
if (!emptyObject(val[i])) {
return false;
}
}
}
return true;
}
function emptyObject(o) {
for (var key in o) {
if (o.hasOwnProperty(key)) {
return false;
}
}
return true;
}
console.log(isEmpty(test2));
Without JQuery: using Array.filter1 and Object.keys2:
function JSONEmpty(obj){
return !obj.length ||
!obj.filter(function(a){return Object.keys(a).length;}).length;
}
// usage
JSONEmpty([{"a":1},{},{}]); //=> false
JSONEmpty([{},{"a":1},{}]); //=> false
JSONEmpty([{},{},{"a":1}]); //=> false
JSONEmpty([]); //=> true
JSONEmpty([{},{},{}]); //=> true
update 2018 Arrow functions are now supported by all modern browsers, so like himel-nag-rana stipulated, you can also use:
const JSONEmpty = obj => !obj.length || !obj.filter(a => Object.keys(a).length).length;
1 More info
2 More info (links contain shims for older browsers)
I had the same problem, and I come with this solution without jQuery:
function isEmpty(x) {
for(var i in x) {
return false;
}
return true;
}
Pretty simple...
if(jQuery.isEmptyObject(test2[0]) && jQuery.isEmptyObject(test2[1]) && jQuery.isEmptyObject(test2[2])))
// do something
Maybe you could try use function like
function isEmptyObject (test) {
for (var i in test) {
if (!jQuery.isEmptyObject(test[i])
return false;
}
return true;
}
Here's my take: turn the array into a set and check for size.
var myArray = [1,2,3];
var mySet = new Set(myArray);
console.log(mySet.size === 0);
check by looping each values in array and return error
Try
for(i=0;js_array[i]!=null;i++)
{
if(js_array[i]=="")
{
alert("Empty");
}
}

How to accomplish this without using eval

Sorry for the title but I don't know how to explain it.
The function takes an URI, eg: /foo/bar/1293. The object will, in case it exists, be stored in an object looking like {foo: { bar: { 1293: 'content...' }}}. The function iterates through the directories in the URI and checks that the path isn't undefined and meanwhile builds up a string with the code that later on gets called using eval(). The string containing the code will look something like delete memory["foo"]["bar"]["1293"]
Is there any other way I can accomplish this? Maybe store the saved content in something other than
an ordinary object?
remove : function(uri) {
if(uri == '/') {
this.flush();
return true;
}
else {
var parts = trimSlashes(uri).split('/'),
memRef = memory,
found = true,
evalCode = 'delete memory';
parts.forEach(function(dir, i) {
if( memRef[dir] !== undefined ) {
memRef = memRef[dir];
evalCode += '["'+dir+'"]';
}
else {
found = false;
return false;
}
if(i == (parts.length - 1)) {
try {
eval( evalCode );
} catch(e) {
console.log(e);
found = false;
}
}
});
return found;
}
}
No need for eval here. Just drill down like you are and delete the property at the end:
parts.forEach(function(dir, i) {
if( memRef[dir] !== undefined ) {
if(i == (parts.length - 1)) {
// delete it on the last iteration
delete memRef[dir];
} else {
// drill down
memRef = memRef[dir];
}
} else {
found = false;
return false;
}
});
You just need a helper function which takes a Array and a object and does:
function delete_helper(obj, path) {
for(var i = 0, l=path.length-1; i<l; i++) {
obj = obj[path[i]];
}
delete obj[path.length-1];
}
and instead of building up a code string, append the names to a Array and then call this instead of the eval. This code assumes that the checks to whether the path exists have already been done as they would be in that usage.

Categories

Resources