I am creating an app in Vue that will filter items in a JSON object. I am having issues with adding a checkbox type filter to this app, because I only want the checkbox filter to run if at least one checkbox is checked, and not to run if none are checked. So currently I have:
computed: {
filteredJobs: function(){
var filteredList = this.jobs.filter(el=> {
return el.title.toUpperCase().match(this.search.toUpperCase())
&& el.employmentType.toUpperCase().match(this.selectedJobType.toUpperCase())
&& el.customText12.toUpperCase().match(this.selectedLocation.toUpperCase())
&& el.dateAdded >= this.checkedDate
});
if (!this.checkedServiceAreas.length) {
return filteredList;
}else{
return filteredList.filter(job => this.checkedServiceAreas.includes(job.categories.data.map(({name}) => name).join(' ')));
}
}
}
So I am doing most of my filtering using select dropdowns, which makes it easy to use the match method to filter the JSON object, but for checkboxes it is a little more difficult because they can be multiple checked. How I currently have it set up is in an IF statement to only filter the checkedServiceAreas if there is at least one checkbox checked. If there isn't just run my normal filtered method.
What I am trying to do is figure out a way to incorporate my IF statement into my filter method without having to do it in two steps like I have above.
return el.title.toUpperCase().match(this.search.toUpperCase())
&& el.employmentType.toUpperCase().match(this.selectedJobType.toUpperCase())
&& el.customText12.toUpperCase().match(this.selectedLocation.toUpperCase())
&& el.dateAdded >= this.checkedDate
&& (this.checkedServiceAreas.length === 0 ||
this.checkedServiceAreas.includes(el.categories.data.map(({name}) => name).join(' '))));
I'm currently writing a little function to take a $scope value from an input field, then add it to a new array containing invited users.
To prevent duplicate entries into the array I'm trying to use JavaScript's filter method.
My problem is when I look at whats being output to the console, the console.log inside the filter function always prints the same Email value, it doesn't seem to update and consider the new input. e.g. a user has added 2 users, the first will be added and the invitesArr will only contain the first Email.
var invitesArr = $scope.invites;
console.log(invitesArr)
console.log($scope.searchContacts)
if ($scope.invites.length >= 0) {
invitesArr.filter(function(invitesArr) {
console.log(invitesArr.Email)
return invitesArr.Email === $scope.searchContacts;
});
if (invitesArr == false) {
courseAccountService.inviteGuestToCourse($scope.courseId,$scope.searchContacts).
then(function(invitation) {
$scope.invites.push(invitation);
});
}
}
Try the below code:
var invitesArr = $scope.invites;
console.log(invitesArr)
console.log($scope.searchContacts)
if ($scope.invites.length >= 0) {
//use arrow operator instead of function.
var duplicateEmails = invitesArr.filter((item) => {
console.log(invitesArr.Email)
//assuming datatype of item.Email and $scope.searchContacts are same else use == for comparision
return item.Email === $scope.searchContacts;
});
//Check for length and then push to your invites
if (duplicateEmails.length==0) {
courseAccountService.inviteGuestToCourse($scope.courseId,$scope.searchContacts).
then(function(invitation) {
$scope.invites.push(invitation);
});
}
}
Hope it helps!!
I have an array of object something like below
Object[0]
canUpload:false
canBeRemoved:true
type:Object
allowMultiple:false
deleted:false
key:"testValue"
Object[1]
canUpload:true
canBeRemoved:true
type:Object
allowMultiple:false
deleted:false
key:"testValue2"
I want to remove an elements from array which contains key:testValue
var myValues = this.testData.data3;
if(!this.testData.canDownload){
myValues= myValues.filter(function(value){
if(!value.canUpload)
return value.type.key==='testValue';
else return false;
});
But its not removing .Whats the right way to do it?
Here is the full code .I can see myValues array of size 2 .If i print myValues after if block its empty.
Code pen:http://codepen.io/developer301985/pen/woGBNg
If your want to filter your array on the basis of two conditions:
canUpload attr is false
type.key is equal to 'testValue'
so you may want to return false in case of canUpload is true to be as follow:
myValues= myValues.filter(function(value) {
if(!value.canUpload)
return value.type.key === 'testValue';
else return false;
});
Otherwise, you just want to filter on type.key is equal to 'testValue', so it will be as follow:
myValues= myValues.filter(function(value) {
return value.type.key === 'testValue';
});
Note, if the callback function you passed into filter returns true, the element will be kept rather than removed. So in your case, you should return false when the value is testValue.
If I understand you correctly, you want to remove item with value.canUpload==false AND type.key === 'testValue'. Then the negate is value.canUpload || value.type.key !== 'testValue'
var myValues = this.testData.data3;
if (!this.testData.canDownload) {
myValues = myValues.filter(function(value) {
return value.canUpload || value.type.key !== 'testValue';
});
}
Let me know whether it works :)
I am trying to create a filtered list projection from a collection of search terms. For instance, if I have one search term, I can do something like this:
if (options.groupKey == "filtered") {
this._items = Data.getItemsFromGroup(this._group);
var query = Windows.Storage.ApplicationData.current.localSettings.values["filters"];
this._items = this._items.createFiltered(function (item) {
if (item.content.search(query) > -1) {
return true
} else {
return false
}
})
}
But what if the 'filters' local setting is a CRLF delimited list, like this:
Cisco
Microsoft
Dell
Currently, the search will compare each term to 'Cisco/nMicrosoft/nDell' which obviously won't work. content.search doesn't accept an array. Should I just do a loop in the createFiltered function somehow? That doesn't seem to be in the spirit of the projection. What is the generally accepted way to do this?
What about storing and object in the "filters" settings where every filter is a property? will that work for you?
if (options.groupKey == "filtered") {
this._items = Data.getItemsFromGroup(this._group);
var query = Windows.Storage.ApplicationData.current.localSettings.values["filters"];
this._items = this._items.createFiltered(function (item) {
return Object.keys(query).indexOf(item) > -1;
})
}
The query object would be something as follows:
{
Cisco: "",
Microsoft: "",
Dell: ""
}
Does that make sense?
edit: made a little change in the code since I believe if (query[item]) would always return false because of javascript type-casting
Please bear with me, I'm pretty new to the whole CouchDb stuff.
The db looks like:
** item ** count ** user **
A 20 bob
B 30 bob
C 10 bob
D 15 john
I want to write a MapReduce that selects all the items belonging to bob and only return the top 2, sorted. so it should return [{item:"B",count:"30"},{item:"A",count:"20}]
I'm not sure how this can be done? Seems like I have to emit(doc.item, doc.count), but how do I know if the user owns the doc? How do I run another MapReduce to select the top elements?
One solution would be to write your view to use a complex key, such as:
function (doc) {
emit([doc.user, doc.count], doc.item);
}
If you add descending=true to your query string, that would give you a view result like:
{"total_rows":4,"offset":0,"rows":[
{"id":"53f359b7cd360da296dd9aab3d0029bd","key":["john",15],"value":"D"},
{"id":"53f359b7cd360da296dd9aab3d001a0e","key":["bob",30],"value":"B"},
{"id":"53f359b7cd360da296dd9aab3d000fec","key":["bob",20],"value":"A"},
{"id":"53f359b7cd360da296dd9aab3d002668","key":["bob",10],"value":"C"}
]}
It's sorted already by user, then count. (with the item type as the value)
Then you can use a _list function to do the rest. The code below basically loops through the view, and returns the top 2 results for each user. If you specify user=bob in the query string, you'll only get the results for bob.
function (head, req) {
// specify that we're sending JSON as our response
provides('json', function () {
var results = [],
result, user, count, row;
while (row = getRow()) {
// if the user doesn't match the last iteration, reset our counter
if (user != row.key[0]) {
user = row.key[0];
count = 0;
}
// we only need the top 2
if (count++ >= 2) {
continue;
}
// start building a result object
result = {
item: row.value,
count: row.key[1]
};
// if we provide user=?
if (req.query.user) {
// check to see if it matches the current user
if (req.query.user === user) {
// if so, add it to the results
results.push(result);
}
// by default, we'll return the top 2 for every user
} else {
// add the user key to the result object
result.user = row.key[0];
// and add it to the result set
results.push(result);
}
}
// send outside the loop, since it needs to be sent as valid JSON
send(JSON.stringify(results));
});
}
If you put user and count in the key of the view, you can use startkey=["bob",""] and endkey=["bob"] to select the user, and descending=true and limit=2 to get the top two items.
I tried the following map function:
function(doc) {
if(doc.user && doc.count && doc.item) {
emit([doc.user, doc.count], doc);
}
}
with the query string ?startkey=["bob",""]&endkey=["bob"]&descending=true&limit=2 it returns:
{"total_rows":4,"offset":1,"rows":[
{"id":"item_B_bob","key":["bob",30],"value":{"_id":"item_B_bob","_rev":"1-b23bd22fb719c7d59b045bce0932df8c","item":"B","count":30,"user":"bob"}},
{"id":"item_A_bob","key":["bob",20],"value":{"_id":"item_A_bob","_rev":"2-515bca46eab383cfeaaa2a101d180291","item":"A","count":20,"user":"bob"}}
]}
Please note:
startkey and endkey are reversed because descending=true.
["bob",""] is a key greater then ["bob", ANY NUMBER] as specified in view collation.