Filtering collections in backbone - javascript

Hello I am running a search of a backbone collection, the current string I am searching is
Project Number
This should return 2 results however it only ever shows 1 result, I cannot understand why, below is the code that I using,
The code the runs when adding search parameters,
updateSearchFilter: function(e) {
var self = this;
this.collection.each(this.filterHide, this);
if($(e.currentTarget).val() === "")
{
this.collection.each(this.filterShow, this);
}
var activeLabels = $(".labels").find(".inactive");
$.each(activeLabels, function(key, index){
switch($(index).attr("id"))
{
case "pending":
status = "7";
self.filterDetails.states["pending"] = false;
break;
case "completed":
status = "5";
self.filterDetails.states["complete"] = false;
break;
case "archived":
status = "3";
self.filterDetails.states["archived"] = false;
break;
case "active":
status = "1";
self.filterDetails.states["active"] = false;
break;
}
});
var visible = this.collection.search($(e.currentTarget).val(), this.filterDetails.states);
if (visible !== undefined) {
visible.each(this.filterShow, this);
}
},
So the above code, hides the idividual results on the first key press, is then loops through an array of jquery objects and re-assigns some values in an object - this is done so we can work out what filters we need to search through.
We then run our search code,
ProjectCollection.prototype.search = function(searchTerm, filters) {
var pattern;
console.log(filters);
pattern = new RegExp(searchTerm, "gi");
if (filters.active && filters.archived) {
if (searchTerm === "") {
return this;
}
return _(this.filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.active) {
if (searchTerm === "") {
return this.active();
}
return _(this.active().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.pending) {
console.log("hello");
if (searchTerm === "") {
return this.pending();
}
return _(this.pending().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.archived) {
if (searchTerm === "") {
return this.archived();
}
return _(this.archived().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
} else if (filters.complete) {
if (searchTerm === "") {
return this.complete();
}
return _(this.complete().filter(function(data) {
return pattern.test(data.get("project_name") + data.get("client_name"));
}));
}
};
ProjectCollection.prototype.archived = function() {
return new ProjectCollection(this.where({
status: '3'
}));
};
ProjectCollection.prototype.active = function() {
return new ProjectCollection(this.where({
status: '1'
}));
};
ProjectCollection.prototype.pending = function() {
return new ProjectCollection(this.where({
status: '7'
}))
};
ProjectCollection.prototype.complete = function() {
return new ProjectCollection(this.where({
status: '5'
}));
}
Now what I should be getting back is 2 results,
Project Number 1 & Project Number 2
However I only every get one result on this search term, Project Number 1 has the status of "Archived" and Project Number 2 has the status of "Pending". However I never seem to get go into the pending portion of the logic (above) even though filters.pending = true;
How can I make sure that I get all the matches for each status returned?

Instead of setting state of your filter individually, you could keep all filter status keys in an array. For example, your user want to filter for active, complete and pending so you would have an array of ['1','5','7']
So when you filter for relevant statuses you could do by
// filterModes is ['1', '5', '7'];
collection.filter(function(model){
return filterModes.indexOf(model.status) !== -1;
}
The rest should be simpler for you now
Note that collection.filter() and collection.where() return array and array may or may not have filter() and definitely don't have where() so be wary about chaining your function call

Related

undefined returned by the some() method

I'm trying to prevent an object that has a bunch of arrays that will contain objects from having duplicated objects (I know it looks weid but try to see my code below you will understand what I'm saying)
JavaScript
var UIController = (function() {
var DOMstrings = {
inputDay: ".optionList",
inputTimeF: ".inputTime",
inputTimeT: ".inputTime2",
inputText: ".inputText",
goingToCkecked: ".checkboxx",
inputBtn: ".add__btn",
planContainer: ".container",
errorCase: ".error-case",
optionList: ".optionList",
optionListId: "#optionList",
errorDes: "error-description",
};
return {
getInput: function() {
return {
inputDay: document.querySelector(DOMstrings.inputDay).value,
inputTimeF: document.querySelector(DOMstrings.inputTimeF).value,
inputTimeT: document.querySelector(DOMstrings.inputTimeT).value,
inputText: document.querySelector(DOMstrings.inputText).value,
goingToCkecked: document.querySelector(DOMstrings.goingToCkecked).checked,
};
},
getDOMstrings: function() {
return DOMstrings;
},
};
})(); //END OF THE UICONTROLLER MODULE
var internalController = (function(UICtrl) {
var Plan = function(id, from, to, text, goingToCkecked) {
this.id = id;
this.from = from;
this.to = to;
this.text = text;
this.goingToCkecked = goingToCkecked;
};
var data = {
Monday: [],
Tuesday: [],
Wednesday: [],
Thursday: [],
Friday: [],
Saturday: [],
Sunday: []
};
function hasObject( day, object ) {
const dataset = data[day];
// console.log(object.inputTimeF);
return dataset.some(el => {
return (
console.log(el.inputTimeF)
//el.inputTimeF=== object.inputTimeF
// el.to === object.to
// el.txt === object.txt
);
});
}
var Dom = UICtrl.getDOMstrings();
return {
addItem: function(day, from, to, text, goingToCkecked) {
var newPlan, ID;
//CREATE NEW ID
if (data[day].length > 0) {
ID = data[day][data[day].length - 1].id + 1;
} else {
ID = 0;
}
//CREATE NEW PLAN BASED ON THE PICKED DAY
if (day === "Monday" || day === "Tuesday" || day === "Wednesday" || day === "Thursday" || day === "Friday" || day === "Saturday" || day === "Sunday") {
newPlan = new Plan(ID, from, to, text, goingToCkecked);
}
//PUSH IT INTO OUR DATA STRUCTURE
data[day].push(newPlan);
//RETURN THE NEW ELEMENT
return newPlan;
}, //END OF THE ADD ITEM METHOD
duplicatedObject: function(day,object) {
return hasObject(day,object);
}
}; //end of the return object of the internal controller module
})(UIController);
var controller = (function(interCtrl, UICtrl) {
var input, newPlan, DOM;
DOM = UICtrl.getDOMstrings();
function setupEventListeners() {
document.querySelector(DOM.inputBtn).addEventListener("click", ctrlAddPlans);
document.addEventListener("keypress", function(e) {
if (e.keyCode === 13) {
document.activeElement.blur();
ctrlAddPlans();
}
});
}
var ctrlAddPlans = function() {
//3.get the filed input data
input = UICtrl.getInput();
// console.log(input);
//5.add the plan to the internalController
newPlan = interCtrl.addItem(input.inputDay, input.inputTimeF, input.inputTimeT, input.inputText, input.goingToCkecked);
// 4.Refuse duplicated plans
var res = interCtrl.duplicatedObject(input.inputDay, input);
console.log(res)
};
return {
init: function() {
console.log('the app has started');
setupEventListeners();
},
};
})(internalController, UIController);
controller.init();
that big object is the data object and he has a bunch of arrays as you are seeing and these arrays will contain objects from some inputs that the user will input.
So when I'm trying to tackle this problem(I don't wanna any array to have duplicated object) I'm using the some() method (try to see the has object function in my code above).
I'm comparing the object's from parmeter and the el's from parameter but I'm getting always false as a returned value so when I tried to debug my code I found that the el.inputTimeF is returning undefined
screenshot
I googled this but I didn't found anything useful
First, make sure that el.inputTimeF is not undefined then you can chage your code like the following:
return dataset.some(el => {
return el.inputTimeF;
});
Last, do not return console.log because it will return undefined.

JavaScript Promise Method not returning any data

I am creating a react native application.
I have a back button that fires the function findItem. findItem the uses async method searchJson. searchJson searches recursive json to find parent object based on id. However it never returns any results.
findItem:
findItem() {
//Pass null so top level json will be pulled
let result = this.searchJson(null).done();
let abv = 2;
// this.setState(previousState => {
// return {
// data: result,
// parentID: result.parentid
// };
// });
}
searchJson:
async searchJson(object) {
return new Promise(resolve => {
//use object or pull from porp - all data
let theObject = object == null ? this.props.data : object;
var result = null;
if (theObject instanceof Array) {
for (var i = 0; i < theObject.length; i++) {
result = this.searchJson(theObject[i]);
if (result) {
break;
}
}
}
else {
for (var prop in theObject) {
console.log(prop + ': ' + theObject[prop]);
if (prop == 'id') {
if (theObject[prop] == this.state.parentID) {
return theObject;
}
}
if (theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
result = this.searchJson(theObject[prop]);
if (result) {
break;
}
}
}
}
if(result != null)
resolve(result);
});
}
Any help will be greatly appreciated.
Ok so I never got this to work but my workaround was this.
I Modified the findItem method:
findItem() {
let FinNode = null;
for (var node in this.props.data) {
FinNode = this.searchJson(this.state.parentID, this.props.data, this.props.data[node].book);
if (FinNode != null) {
this.setState(previousState => {
return {
data: FinNode[0].book.parentid == "" ? null : FinNode,
parentID: FinNode[0].book.parentid
};
});
break;
}
}
}
And then the searchJson:
searchJson(id, parentArray, currentNode) {
if (id == currentNode.id) {
return parentArray;
} else {
var result;
for (var index in currentNode.books) {
var node = currentNode.books[index].book;
if (node.id == id)
return currentNode.books;
this.searchJson(id, currentNode.books, node);
}
return null;
}
}
This allowed for all my nodes to be searched and the for loop made so that there is no need for async. This does have some drawbacks but seems to work decently without any massive performance issues.

how to return value inside of forEach loop in JavaScript

I got stuck with my code.
I wrote this sample code only for the purpose to reproduce my problem, so this code is not practical at all but I hope you get my point.
In the code below, for the last value to be output, I expect it to be 3, but it's undefined.
How am I supposed to write if I want the last value to be 3 in this case??
This is just a sample code, but in the actual code, I fetch content from amazon api and when it returns api error, I want to run the same function again after 1000 milli seconds.
var list = [1,2,3];
var someClass = new SomeClass();
list.forEach(function(value) {
var result = someClass.getSomething(value);
console.log("outside: " + result);
});
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
this.getSomething(something);
//I need to return here, so the succeeding code is not read.
return;
}
console.log("inside: " + String(something));
return something;
}
}
Log
inside: 1
outside: 1
inside: 2
outside: 2
inside: 3
outside: undefined // I expect this value to be 3!!!
You have a test:
if (something === 3 && flag === false) {
//...
return;
If you want to return 3 then don't have a return statement with nothing after it. return means return undefined. Put return 3 or return something.
You probably want to return from your recursive call though:
return this.getSomething(something);
Here's the problem:
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
this.getSomething(something); // not returning this
return; // returning undefined
}
console.log("inside: " + String(something));
return something;
}
}
Here's the fix:
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
return this.getSomething(something);
}
console.log("inside: " + String(something));
return something;
}
}
change the code to
if (something === 3 && flag === false)
{
flag = true;
return this.getSomething(something);
}
"return;" returns undefined
It returns undefined in your code because you return; in the if clause.
return this.getSomething(something) within the if clause
var list = [1, 2, 3];
var someClass = new SomeClass();
list.forEach(function(value) {
var result = someClass.getSomething(value);
console.log("outside: " + result);
});
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
return this.getSomething(something);
}
console.log("inside: " + String(something));
return something;
}
}
forEach loop doesn't return a value.
You can create a global variable and assign values to it.

Meteor template doesn't re-render even though its helper is called?

Ive got this template on the front end:
if tournament
.tournament
if round
each round
ul(class='round#{currentRound} of#{rounds}')
each match
li
each participant
if winner
.participant.winner
a(href='#')
span.participant-title #{displayName}
span.participant-number #{rank}
span.participant-id #{id}
span.participant-status #{status}
span.participant-round #{thisRound}
span.participant-match #{thisMatch}
else if pending
.participant
a(href='#')
span.participant-title Waiting...
span.participant-number xxx
span.participant-id #{id}
span.participant-status #{status}
span.participant-pending
span.participant-disagree #{disagree}
span.participant-round #{thisRound}
span.participant-match #{thisMatch}
else
.participant.loser
a(href='#')
span.participant-title #{displayName}
span.participant-number #{rank}
span.participant-id #{id}
span.participant-status #{status}
span.participant-round #{thisRound}
span.participant-match #{thisMatch}
else
h1#not-found Tournament Not Found
and this helper:
tournament: function(){
if (this.tournament) {
return true;
}else{
return false;
}
},
round: function() {
var tournament = this.tournament.brackets;
var rounds = tournament.length;
var results = [];
tournament.map(function(value, index){
var currentRound = index + 1;
results.push({rounds: rounds, currentRound: currentRound, matches: value});
});
return results;
},
match: function(){
return this.matches;
},
participant: function(){
var results = [];
this.map(function (value, index) {
var type = value['win'];
var obj = {
id: value['id'],
rank: value['id'].slice(0,3),
displayName: value['displayName'],
thisRound: value['round'],
thisMatch: value['match'],
status: type,
disagree: value['disagree']
};
if (value['disagree']) {
console.log("value:", value);
}
if (type === true || type === 'undetermined') {
obj.winner = true;
}else if (type === 'pending'){
obj.pending = true;
}else{
obj.loser = true;
}
results.push(obj);
});
return results;
}
The helper is getting ran everytime the tournament object changes... but the template only gets updated the first time my meteor method is called?
have you ever encoutered this before?
I can post my meteor method if that would help too.
Where I change data:
Meteor.call('submitWinner', winnerInfo, thisCampaign._id, Meteor.user().apiKey, function(error, result) {
// display the error to the user and abort
if (error){
return alert(error.reason);
}else{
// update css?
var updateWaiting = $('.last-submitted').closest('.participant');
// updateWaiting.html('<a href=#><span class=participant-title>Waiting...</span> <span class=participant-number>xxx</span></a>');
// updateWaiting.removeClass('undetermined')
$('#theaterMode').hide();
$('.swearBox').hide();
}
});

Checking multiple variables' values to make sure they all match

How do I efficiently check to see if multiple variables' values all match? The following function should return true if they match and false if they don't:
function projectIsLocked (data) {
if (data.ArchiveSnapshotID === data.CurrentSnapshotID === data.LiveSnapshotID) {
return true;
}
return false;
}
I thought I could just use if (data.ArchiveSnapshotID === data.CurrentSnapshotID === data.LiveSnapshotID) but it doesn't seem to work.
Ideas for something simple?
If there are just 3 comparisons , then this should be enough.
function projectIsLocked (data) {
var archive = data.ArchiveSnapshotID;
var current = data.CurrentSnapshotID;
var live = data.LiveSnapshotID;
return (archive === current && current === live)
}
Why not push them all to an array. This way you can use as many.
function check_for_equal_array_elements(my_array){
if (my_array.length == 1 || my_array.length == 0) {
return true;
}
for (i=0;i<my_array.length;i++){
if (i > 0 && my_array[i] !== my_array[i-1]) {
return false;
}
}
return true;
}
//Example:
var my_array = [];
my_array.push(5);
my_array.push(5);
// will alert "true"
alert("all elements equal? "+check_for_equal_array_elements(my_array));
my_array.push(6);
// will alert "false"
alert("all elements equal? "+check_for_equal_array_elements(my_array));
The problem here is, that a part of the logical expression is evaluated and then compared, so data.ArchiveSnapshotID === data.CurrentSnapshotID evaluated to "true" and data.LiveSnapshotID is checked against true, which you can see here (LiveSnapshotID was changed to boolean true):
function projectIsLocked (data) {
if (data.ArchiveSnapshotID === data.CurrentSnapshotID === data.LiveSnapshotID) {
return true;
}
return false;
}
var data = { ArchiveSnapshotID: "foo", CurrentSnapshotID: "foo", LiveSnapshotID: true };
alert(projectIsLocked (data));
You might want to use something like this, which is quite extensible for even more properties.
function projectIsLocked (data) {
var props = ["ArchiveSnapshotID", "CurrentSnapshotID", "LiveSnapshotID"];
for (var i = 1; i < props.length; i++)
{
if (data[props[i]] !== data[props[i - 1]])
return false;
}
return true;
}

Categories

Resources