Update collection object using Underscore / Lo-dash - javascript

I have two collections of objects. I iterate trough collection A and I want when ObjectId from A matches ObjectId from B, to update that Object in collection B.
Here is what I got so far:
var exerciseIds = _(queryItems).pluck('ExerciseId').uniq().valueOf();
var item = { Exercise: null, ExerciseCategories: [] };
var exerciseAndCategories = [];
//this part works fine
_.forEach(exerciseIds, function(id) {
var temp = _.findWhere(queryItems, { 'ExerciseId': id });
item.Exercise = temp.Exercise;
exerciseAndCategories.push(item);
});
//this is problem
_.forEach(queryItems, function (i) {
_(exerciseAndCategories).where({ 'ExerciseId': i.ExerciseId }).tap(function (x) {
x.ExerciseCategories.push(i.ExerciseCategory);
}).valueOf();
});
EDIT
Link to a Fiddle

Give this a try:
var exerciseIds = _(queryItems).pluck('ExerciseId').uniq().valueOf();
var item = {
Exercise: null,
ExerciseCategories: []
};
var exerciseAndCategories = [];
//this part works fine
_.forEach(exerciseIds, function (id) {
var temp = _.findWhere(queryItems, {
'ExerciseId': id
});
var newItem = _.clone(item);
newItem.Exercise = temp.ExerciseId;
exerciseAndCategories.push(newItem);
});
//this is problem
_.forEach(queryItems, function (i) {
_(exerciseAndCategories).where({
'Exercise': i.ExerciseId
}).tap(function (x) {
return _.forEach(x, function(item) {
item.ExerciseCategories.push(i.ExerciseCategory);
});
}).valueOf();
});
// exerciseAndCategories = [{"Exercise":1,"ExerciseCategories":["biking","cardio"]},{"Exercise":2,"ExerciseCategories":["biking","cardio"]}]
Main problem was that tap returns the array, not each item, so you have to use _.forEach within that.
FIDDLE

Related

javascript adding object to an array

this.journeyIds = ["source", "destination"];
this.journeyDetails = [];
this.journeyIds.map((id)=>{
this.journeyDetails.push({
id: this.el("#" + id).inputValue
});
});
I want array like [{Source : "LMP"}, {Destination : "LKO"}];
i.e I want to make Id as key in object
thank you!
It seems that you want the id as key of an object. Use [] around the id
this.journeyIds = ["source", "destination"];
this.journeyDetails = [];
this.journeyIds.map((id) => {
this.journeyDetails.push({[id] :
this.el("#"+id).inputValue});
});
I don't have the function this.el() so it's an array here, you could just replace it with the function call (this.el["#"+id].inputValue => this.el("#"+id).inputValue
this.journeyIds = ["source", "destination"];
this.journeyDetails = [];
this.el = {
"#source": {inputValue: "foo"},
"#destination": {inputValue: "bar"}
}
this.journeyIds.forEach((id) => {
let temp = {};
temp[id] = this.el["#"+id].inputValue;
this.journeyDetails.push(temp);
});
console.log(this.journeyDetails)

Updating an AND filter to OR filter Javascript

I'm working on a JavaScript filter that needs to show all items that are tagged with the related values. At the moment I have it working so that it shows items that have have each of these values assigned rather than showing the items as long as they have one of the values assigned.
So for example, if I check Cats and Dogs, I want to show every post that has either of these values assigned, rather than just showing items that have both assigned.
My code example is below:
var $filterCheckboxes = $('input[type="checkbox"], input[type="radio"]');
$filterCheckboxes.on('change', function() {
var selectedFilters = {};
$filterCheckboxes.filter(':checked').each(function() {
if (!selectedFilters.hasOwnProperty(this.name)) {
selectedFilters[this.name] = [];
}
selectedFilters[this.name].push(this.value);
});
var $filteredResults = data;
// console.log('filtered data: ' + $filteredResults);
$.each(selectedFilters, function(name, filterValues) {
$filteredResults = $filteredResults.filter(function(item) {
var matched = false,
currentFilterValues = item.Tags;
console.log(currentFilterValues);
$.each(currentFilterValues, function(_, currentFilterValue) {
if ($.inArray(currentFilterValue, filterValues) != -1) {
matched = true;
return false;
console.log(currentFilterValue);
}
});
return matched;
});
});
Any assistance would be appreciated.
I went down a different route and minimised the code to get it running the way I desired:
var $filterCheckboxes = $('input[type="checkbox"], input[type="radio"]');
$filterCheckboxes.on('change', function() {
var $filteredResults = data;
var selectedFilters = [];
$filterCheckboxes.filter(':checked').each(function() {
selectedFilters.push(this.value);
});
$filteredResults = data.filter(function(item) {
return (_.intersection(item.Tags, selectedFilters).length > 0);
});
});
So now every time a checkbox was checked, it would see if the selected tag(s) matched the tags within the item(s), if so it would grab any matching items and show them in the list.

How to update JavaScript array dynamically

I have an empty javascript array(matrix) that I created to achieve refresh of divs. I created a function to dynamically put data in it. Then I created a function to update the Array (which I have issues).
The Data populated in the Array are data attributes that I put in a JSON file.
To better undertand, here are my data attributes which i put in json file:
var currentAge = $(this).data("age");
var currentDate = $(this).data("date");
var currentFullName = $(this).data("fullname");
var currentIDPerson = $(this).data("idPerson");
var currentGender = $(this).data("gender");
Creation of the array:
var arrayData = [];
Here is the function a created to initiate and addind element to the Array :
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
var isFound = false;
// search if the unique index match the ID of the HTML one
for (var i = 0; i < arrayData.length; i++) {
if(arrayData[i].idPerson== p_currentIDPerson) {
isFound = true;
}
}
// If it doesn't exist we add elements
if(isFound == false) {
var tempArray = [
{
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate, currentAge: p_currentAge
}
];
arrayData.push(tempArray);
}
}
The update function here is what I tried, but it doesn't work, maybe I'm not coding it the right way. If you can help please.
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
for (var i = 0; i < arguments.length; i++) {
for (var key in arguments[i]) {
arrayData[i] = arguments[i][key];
}
}
}
To understand the '$this' and elm: elm is the clickableDivs where I put click event:
(function( $ ) {
// Plugin to manage clickable divs
$.fn.infoClickable = function() {
this.each(function() {
var elm = $( this );
//Call init function
initMatrixRefresh(elm.attr("idPerson"), elm.data("gender"), elm.data("fullname"), elm.data("date"), elm.data("age"));
//call function update
updateMatrix("idTest", "Alarme", "none", "10-02-17 08:20", 10);
// Définition de l'evenement click
elm.on("click", function(){});
});
}
$('.clickableDiv').infoClickable();
}( jQuery ));
Thank you in advance
Well... I would recommend you to use an object in which each key is a person id for keeping this list, instead of an array. This way you can write cleaner code that achieves the same results but with improved performance. For example:
var myDataCollection = {};
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (!myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
Depending on your business logic, you can remove the if statements and keep only one function that adds the object when there is no object with the specified id and updates the object when there is one.
I think the shape of the resulting matrix is different than you think. Specifically, the matrix after init looks like [ [ {id, ...} ] ]. Your update function isn't looping enough. It seems like you are trying to create a data structure for storing and updating a list of users. I would recommend a flat list or an object indexed by userID since thats your lookup.
var userStorage = {}
// add/update users
userStorage[id] = {id:u_id};
// list of users
var users = Object.keys(users);

Javascript variable is an array of objects but can't access the elements

I am using Firebase database and Javascript, and I have code that will get each question in each category. I have an object called category will contain the name, the questions, and the question count, then it will be pushed into the list of categories (questionsPerCategory). Inside the the callback function I just do console.log(questionsPerCategory). It prints the object (array) that contains the categories and questions. Now my problem is that when I do console.log(questionsPerCategory[0]) is says it's undefined, I also tried console.log(questionsPerCategory.pop()) since it's an array but it's also undefined. Why is that? Below is the code and the image of the console log. Additional note: CODE A and C are asynchronous, CODE B and D are synchronous.
this.getQuestionsForEachCategory = function(callback, questions, questionsPerCategory) {
var ref = firebase.database().ref('category');
var questionRef = firebase.database().ref('question');
console.log('get questions for each category');
// CODE A
ref.once("value", function(snapshot) {
// CODE B
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childData = childSnapshot.val();
var category = {
category_name: childData.category_name
};
// CODE C
questionRef.orderByChild("category_name").equalTo(childData.category_name).once("value", function(questionSnapshot){
var count = 0;
var q = [];
// CODE D
questionSnapshot.forEach(function(childQuestionSnapshot) {
var questionObj = childQuestionSnapshot.val();
count++;
questions.push(questionObj.question);
q.push(questionObj.question);
});
category.questions = q;
category.questionCount = count;
questionsPerCategory.push(category);
});
});
callback(questionsPerCategory);
});
};
The callback(questionsPerCategory); should happen when all async calls are finished.
Right now the questionsPerCategory is not ready when the callback is called.
I would use Promise API to accomplish this.
Depending on the Promise library you are using, this can be accomplished in a different ways, e.g. by using bluebird it looks like you need map functionality.
Try this code:
this.getQuestionsForEachCategory = function(callback, questions) {
var ref = firebase.database().ref('category');
var questionRef = firebase.database().ref('question');
console.log('get questions for each category');
var questionsPerCategory = [];
// CODE A
ref.once("value", function(snapshot) {
// CODE B
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childData = childSnapshot.val();
var category = {
category_name: childData.category_name
};
// CODE C
questionRef.orderByChild("category_name").equalTo(childData.category_name).once("value", function(questionSnapshot){
var count = 0;
var q = [];
// CODE D
questionSnapshot.forEach(function(childQuestionSnapshot) {
var questionObj = childQuestionSnapshot.val();
count++;
questions.push(questionObj.question);
q.push(questionObj.question);
});
category.questions = q;
category.questionCount = count;
questionsPerCategory.push(category);
});
callback(questionsPerCategory);
});
});
};

nested for loop in javascript knockout

I have two observable arrays:
var viewModel = {
PositionTypes: ko.observableArray([]),
Users: ko.observableArray([])
}
POSITION ViewModel
var positionViewModel = function (data) {
var _self = this;
_self.PositionName = ko.observable(data.PositionName);
_self.PositionRank = ko.observable(data.PositionRank);
_self.ContentRole = ko.observable(data.ContentRole);
}
positionViewModel.AddPositions = function (data) {
$.each(data, function (index, value) {
positionViewModel.PushPosition(value);
});
};
positionViewModel.PushPosition = function (postion) {
viewModel.PositionTypes.push(new positionViewModel(position));
};
USER ViewModel
// the ViewModel for a single User
var userViewModel = function (data) {
var _self = this;
_self.ID = ko.observable(data.ID);
_self.Name = ko.observable(data.Name);
_self.Email = ko.observable(data.Email);
_self.ContentRole = ko.observable(data.ContentRole);
};
userViewModel.AddUsers = function (data) {
$.each(data, function (index, value) {
userViewModel.PushUser(value);
});
};
userViewModel.PushUser = function (user) {
viewModel.Users.push(new userViewModel(user));
};
How can i using linq.js so that i could loop through every position so i could get all the users for each position?
foreach( each position in positions)
{
foreach(each user in users)
{ list of users for the position}
}
You could also use ko.utils.arrayForEach as follow :
ko.utils.arrayForEach(viewModel.PositionTypes(), function(position){
var usersInPosition = ko.utils.arrayFilter(viewModel.Users(), function(user){
return user.ContentRole() == position.ContentRole();
});
ko.utils.arrayForEach(usersInPosition, function(user){
});
});
See doc
I hope it helps.
Using linq.js, you can perform a join on the columns you want to compare.
Assuming you are joining between the ContentRoles:
var query = Enumerable.From(viewModel.PositionTypes())
.GroupJoin(viewModel.Users(),
"$.ContentRole()", // position selector
"$.ContentRole()", // user selector
"{ Position: $, Users: $$.ToArray() }")
.ToArray();
So I think you want to create an object that contains a mapping of all the positions and user names. You can create such an object using the Aggregate() function to collect all the results into a single object.
var userPositions = Enumerable.From(this.PositionTypes())
.GroupJoin(this.Users(),
"$.ContentRole()", // position selector
"$.ContentRole()", // user selector
"{ Position: $, Users: $$ }") // group all users per position
.Aggregate(
{}, // start with an empty object
function (userPositions, x) {
var positionName = x.Position.PositionName(),
userNames = x.Users.Select("$.Name()").ToArray();
// add the new property
userPositions[positionName] = userNames;
return userPositions;
}
);

Categories

Resources