Perform conditional map join - javascript

I have to join an array of javascript object property, but to add the property value to the string I have to check if another property is not undefined or false:
What I do now:
var out = [];
$scope.grid.dataSource.data().map(function (user) {
if (angular.isDefined(user.Selected) && user.Selected == true)
out.push(user.UserPersonID);
});
var ids = out.join(",");
I'd like do something like this:
var ids = $scope.grid.dataSource.data().map(function (user) { if (user.Selected) return user.UserPersonID; }).join(",");
But if the user.Selected is not true I'll obtain a long list of , ('123,,,234,,,').
How can I get the same result without using the out array?

You're looking for the Array filter method:
var out = $scope.grid.dataSource.data().filter(function(user) {
return angular.isDefined(user.Selected) && user.Selected;
}).map(function (user) {
return user.UserPersonID;
});

Related

How to filter an array by two indvidual strings from an object?

I'm working on a project where I need to filter 13 items by two different select box values, and I'm getting stuck on persisting the filter.
I have two select boxes that I've selected like so:
let pickupLocation = document.querySelector("#pa_location"); //values are 'complete-set', 'neck', 'bridge'.
let pickupType = document.querySelector("#pa_type1"); // Values are 'soapbar', 'dogear', 'short'.
What's Working:
I'm initializing an object like so:
const activeFilters = {};
To populate the values like so:
//Persist the Complete Set / Single
pickupLocation.addEventListener("change", function () {
if (pickupLocation.value === "complete-set") {
activeFilters.location = "set";
} else {
activeFilters.location = "single";
}
});
pickupType.addEventListener("change", function () {
if (pickupType.value === "soapbar") {
activeFilters.type = "soapbar";
} else if (pickupType.value === "dogear") {
activeFilters.type = "dogear";
} else {
activeFilters.type = "short";
}
});
// Returns something like
// {location: single, type: dogear}
I'm trying to filter an array of input elements by their value. I have 13 inputs each with a value containing words like set, single, dogear, soapbar etc.
Where I'm stuck:
I have a filter function that I'm trying to filter the values of these inputs by two values of the activeFilters object:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
results = covers.filter((cover) => cover.value.indexOf(value) !== -1);
});
return results;
};
The problem is my function is returning only one of the two words. For instance, if the my activeFilters object is {location: set, type: dogear} the filtered results array contains only one of them. Where am I going wrong?
Edit:
This function returns all inputs that match one of the activeFilters, and I apologize if I wasn't clear above, but I'd like it to match ALL of the Active Filters. Is this possible with the function below?
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
results.push(...res);
});
console.log(results);
};
CODEPEN:
Codepen!
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
// push the value it find individually
// you were overriding the previous value with result = filter()
results.push(...res);
});
return results;
};
// according to Edited question
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
return covers.filter((cover) => filteredValues.every(value => cover.value.indexOf(value) !== -1));
};
I'm not sure if I understood clearly your question, so feel free to comment it.
First, I suggest you to filter your covers array and inside the filtering function iterate through your selected filters. This is because the filter function returns the array already filtered and so you don't need to assign it to a result variable or things like that. So based on that, try this:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
const filteredCovers = covers.filter((cover) => {
return cover.value.split("-").some((tag) => filteredValues.includes(tag))
});
console.log(filteredCovers)
};

How to get value from one of several possible URL parameters?

I want to retrieve values form url parameters, but the parameters are not constant: it can be "referer=" or "utm_source=" or "source=".
I can get the value with
url.searchParams.get("referer");
Complete script for now :
function() {
var url_string = window.location.href;
var url = new URL(url_string);
var ref = url.searchParams.get("referer");
if (ref == undefined) {
return "No Referer";
} else {
return ref;
}
}
Can I include some regex like:
var ref = url.searchParams.get.match(/referer|source|utm\_source/g);
Can I include some regex
No. That isn't a feature of get.
You can use a set of ||s:
var ref = url.searchParams.get("referer") || url.searchParams.get("source") || url.searchParams.get("utm_source");
Or take an array of key names, map them to the values in the URL, filter out any which don't have a value, then take the first (and presumably only) value off the array.
var possible_key_names = ["referer", "source", "utm_source"];
var ref = possible_key_names
.map(name => url.searchParams.get(name))
.filter(value => !!value)
.shift();
You can loop over the searchParams like so:
var url = new URL("https://example.com/page?referer=&utm_source=google");
var value;
for (var [key, val] of url.searchParams) {
if (key.match(/^(referer|source|utm_source)$/) && val !== "") {
value = val;
break;
}
}
console.log(value);

AngularJS check condition and return true or false

I have html like this :
<td><span ng-if="isuser(user) == false" type="button" >not allowed</span> </td>
the above html is displayed only if the function isuser(user) return false.
I have an array like this :
$scope.list = ["456", "111", "459"];
Now the user object has an array called id. This id array contains a number key whose value can be 456,111 or 459 and sometimes it may be empty also.
The user object :
{"name":"pravin","status":"Live","id":[{"number":"111"}],"msg":"test"}
Here is the isuser function :
$scope.isuser = function(user) {
for (var i = 0; i < $scope.list.length; i++){
var exists = user.id.find(({number}) => number === $scope.list[i]);
}
if (exists)
return true;
else
return false;
};
but this always returns false.
I want the for loop to check if none of the values of the number key exists in the list array and then only return false.
How do I do it?
The issue is that the below statement
var exists = user.id.find(({number}) => number === $scope.list[i]);
updates every time the exists variable and always you'll get the last change.
One approach could be using some method by passing a callback function as argument.
$scope.isuser = function(user) {
var exists = user.id.some(({number}) => $scope.list.includes(number));
return exists;
}
Try this it will help you
$scope.isuser = function(user) {
var exists = false;
for (var i = 0; i < $scope.list.length; i++){
exists = user.id.find(({number}) => number === $scope.list[i]);
}
if(i==$scope.list.length-1){
if (exists)
return true;
else
return false;
}
loop };

pg-promise create custom filters for select query

The function that I am working on is getting an input object that has 7 different key-values and each of them could be undefined or not. I want to filter my database based on those key-values that exists in the input. For example if only input.userID exists I want to run this query:
db.query("...WHERE userID = ${userID}", {userID: input.userID});
else if both input.userID and input.startTime exist, I want to do this:
db.query("...WHERE userID = ${userID} and startTime= ${startTime}", {userID: input.userID, startTime: input.startTime});
What I have done is I created a params and keys object like this:
if(input.userID) {
keys.push('userID');
params.push(input.userID);
query = addFilterToTheQuery(query, 'userID', input.userID, filteredItemsCount);
filteredItemsCount = filteredItemsCount +1;
}
addFilterToTheQuery is a simple function I implemented myself. I basically make 7 if cases. Then I have to use those keys and param values to pass to the query function in a way that might need another huge switch case code.
Is this the only way to do this? Is there a better way to get rid of the redundancies in this code?
Custom Type Formatting is the most suitable here.
For example, if we want to convert an object with properties - filter values, we could do it like this:
var pgp = require('pg-promise')(/* initialization options */);
function FilterSet(filters) {
if (!filters || typeof filters !== 'object') {
throw new TypeError('Parameter \'filters\' must be an object.');
}
this._rawDBType = true; // property renamed later - see UPDATE below
this.formatDBType = function () {
var keys = Object.keys(filters);
var s = keys.map(function (k) {
return pgp.as.name(k) + ' = ${' + k + '}';
}).join(' AND ');
return pgp.as.format(s, filters);
};
}
TEST
var filter = new FilterSet({
first: 1,
second: 'two'
});
var test = pgp.as.format('WHERE $1', filter);
console.log(test);
This outputs:
WHERE "first" = 1 AND "second" = 'two'
If your filters are to be used as %value% with LIKE or ILIKE, then you would need to change your custom type accordingly.
See related questions:
42, 49, 89, 90,
UPDATE
Below is the same example re-written for the latest pg-promise (version 8.x or newer):
const pgp = require('pg-promise')(/* initialization options */);
class FilterSet {
constructor(filters) {
if (!filters || typeof filters !== 'object') {
throw new TypeError('Parameter \'filters\' must be an object.');
}
this.filters = filters;
this.rawType = true; // do not escape the result from toPostgres()
}
toPostgres(/*self*/) {
// self = this
const keys = Object.keys(this.filters);
const s = keys.map(k => pgp.as.name(k) + ' = ${' + k + '}').join(' AND ');
return pgp.as.format(s, this.filters);
}
}
See Custom Type Formatting.

Dynamic arrays in Javascript/JQuery

Why does my array length always come out to 0 even though var email is equal to a string. (I've alerted out var email and the data is there).
var emails = new Array();
//get all the emails
$('.emailBox input').each(function (i)
{
var email = $(this).val();
if(email != '')
{
emails[email] = email;
alert(emails.length);
}
});
Because you're adding a property to the array.
var a = [];
a.foo = 42;
a.length === 0; // true
Instead try
emails.push(email);
This is the same as emails[emails.length] = email
As an aside:
var emails = new Array();
Is bad. You should be using [] instead of new Array() mainly because it's more terse and readable.
if (email != '') {
The above can be replace with if (email) { in case jQuery ever returns undefined or null
To make the entire code more elegant you should use
var emails = $('.emailBox input').map(function() {
return this.value;
}).filter(function (k, v) { return v; }).get();
Or without jQuery
var emails = [].map.call(document.querySelectorAll(".emailBox input"), function (v) {
return v.value;
}).filter(function (v) { return v; });
Although you'll need a QSA shim and a ES5 shim for legacy platform support.
Edit:
If you want the array to be unique then reduce it.
var arr = arr.reduce(function (memo, val, key, arr) {
// if the first index of the value is the index then add it.
// if the first index is different then we already have it.
if (arr.indexOf(val) === key) {
memo.push(val);
}
return memo;
}, []);
You could do all of that using a few jQuery methods.
var emails = $('.emailBox input')
.map(function() { return $(this).val() || null; })
.get();
jsFiddle.
emails[email] = email isn't doing what you want it to do. Try
emails.push(email);

Categories

Resources