javascript push() method for adding object to array of objects - javascript

var model = {
cats: [
{
clickCount: 0,
name: "Panther",
imgUrl: "images/cat1.png"
},
{
clickCount: 0,
name: "Tiger",
imgUrl: "images/cat2.png"
},
{
clickCount: 0,
name: "Rocky",
imgUrl: "images/cat3.png"
},
{
clickCount: 0,
name: "Marshal",
imgUrl: "images/cat4.png"
},
{
clickCount: 0,
name: "Simpson",
imgUrl: "images/cat5.png"
},
{
clickCount: 0,
name: "Kajol",
imgUrl: "images/cat6.png"
}
]
};
catObject = {
name: document.getElementById('text-name').value,
url: document.getElementById('text-url').value,
count: document.getElementById('text-count').value
};
model is an array of objects. I am trying to add another object using model.cats.push(catObject);
where text-name, text-url, text-count are ids of textboxes in a form.
I am not getting desired results. I am seeing that only catObject.name is getting pushed onto model.cats and catObject.url and catObject.count is not getting added and hence 'undefined' are values of the model.cats.imgUrl and model.cats.clickCount.
I can add full code if required. I tried so may things.. Could someone check if I am missing anything here? Thanks in advance.

Correction
model is not an array of objects rather model is an object that contains a property (i.e. cats) which is an array of objects.
You're correct
From your description, it is clear that you have successfully pushed catObject into cats using model.cats.push(catObject);
What went wrong
You might have used loop to access the elements inside cats array and got undefined for model.cats.clickCount and model.cats.imgUrl of only the last object you've pushed because you named properties of catObject as url and count (i.e. instead of imgUrl and clickCount). So, just change the property names to imgUrl and clickCount to fix the issue.
Corrected code here

Related

Why javascript array sort doesn't compare all elements with each other?

I'm trying to understand why Javascript array sort doesn't work with the following logic. I have no problems making my own algorithm to sort this array, but I'm trying to make it with the Javascript sort built-in method to understand it better.
In this code, I want to push entities that "belongs to" another entity to the bottom, so entities that "has" other entities appear on the top. But apparently, the sort method doesn't compare all elements with each other, so the logic doesn't work properly.
Am I doing something wrong, or it is the correct behavior for the Javascript sort method?
The code I'm trying to execute:
let entities = [
{
name: 'Permission2',
belongsTo: ['Role']
},
{
name: 'Another',
belongsTo: ['User']
},
{
name: 'User',
belongsTo: ['Role', 'Permission2']
},
{
name: 'Teste',
belongsTo: ['User']
},
{
name: 'Role',
belongsTo: ['Other']
},
{
name: 'Other',
belongsTo: []
},
{
name: 'Permission',
belongsTo: ['Role']
},
{
name: 'Test',
belongsTo: []
},
]
// Order needs to be Permission,
let sorted = entities.sort((first, second) => {
let firstBelongsToSecond = first.belongsTo.includes(second.name),
secondBelongsToFirst = second.belongsTo.includes(first.name)
if(firstBelongsToSecond) return 1
if(secondBelongsToFirst) return -1
return 0
})
console.log(sorted.map(item => item.name))
As you can see, "Role" needs to appear before "User", "Other" before "Role", etc, but it doesn't work.
Thanks for your help! Cheers
You're running into literally how sorting is supposed to work: sort compares two elements at a time, so let's just take some (virtual) pen and paper and write out what your code is supposed to do.
If we use the simplest array with just User and Role, things work fine, so let's reduce your entities to a three element array that doesn't do what you thought it was supposed to do:
let entities = [
{
name: 'User',
belongsTo: ['Role', 'Permission2']
},
{
name: 'Test',
belongsTo: []
},
{
name: 'Role',
belongsTo: ['Other']
}
]
This will yield {User, Test, Role} when sorted, because it should... so let's see why it should:
pick elements [0] and [1] from [user, test, role] for comparison
compare(user, test)
user does not belong to test
test does not belong to user
per your code: return 0, i.e. don't change the ordering
we slide the compare window over to [1] and [2]
compare(test, role)
test does not belong to role
role does not belong to test
per your code: return 0, i.e. don't change the ordering
we slide the compare window over to [2] and [3]
there is no [3], we're done
The sorted result is {user, test, role}, because nothing got reordered
So the "bug" is thinking that sort compares everything-to-everything: as User and Role are not adjacent elements, they will never get compared to each other. Only adjacent elements get compared.

VueFire watch for empty array property

looking around for a solution for my problem!
I try to make Vue.Draggable work with VueFire. I have a few lists with cards that can be dragged between them, sorted, cloned and so on. While the lists are populated with cards Vue.Draggable works perfectly, it watches for changes, triggers events like magic.
This is the working JSON:
categories: [{
name: "todo",
cards: ["second","first","second"]
},{
name: "doing"
cards: ["first","fourth","second"]
},{
name: "done",
cards: ["second", "fourth","first","third"]
}]
The problem comes when one o the lists is empty. We all know that Firebase doesn't store empty properties that's why Vue.Draggable can't watch for a property that doesn't exist. For example like this:
categories: [{
name: "todo",
cards: ["second","first","second"]
},{
name: "doing"
// missing cards property because it's empty
},{
name: "done",
cards: ["second", "fourth","first","third"]
}]
The cards property should be filled with values by dragging items to the list, but because cards doesn't exist Vue.Draggable can't watch for changes in that list and can't trigger events.
Is there a way to create some kind of placeholder or middleware to simulate that empty array? Or what are other possible solutions in this case?
Here's a small JSFiddle.
Thank you!
Why don't you initialize the cards property if nothing is returned from firebase?
categories: [{
name: "todo",
cards: ["second","first","second"]
},{
name: "doing",
cards: firebaseCollectionProperty || []
},{
name: "done",
cards: ["second", "fourth","first","third"]
}]

How to write this Store structure?

I'm trying to figure out the best way for my Redux Store to handle lists. Right now it looks like this:
Store = {
users: [],
posts: [],
lists: [],
}
My problem with this, is the list array. Essentially it's a store for paginated lists of a specific resource, so for example:
lists: [
{
id: 'users/43/posts',
items: [25, 36, 21]
}
]
Since I am using the url as the id, my component that shows a user's list of posts will know exactly which list to display. Now someone has told me that, this is a very very bad idea. And I just want some advice on what could be better. Another approach suggested was this:
users: [{
id: 2,
posts: [
{
url: 'users/2/posts',
items: [13, 52, 26],
}
]
}]
So what I don't understand, how does Redux know where to save this list? Do I have to specify in the action arguments where to save it?
Thank you for your advice.
Well, technically, anything works if you make it work! The second approach looks more mature, though. You don't want to use URLs as ID. IDs should be numbers or special sequence of characters+numbers. When your application grows, you'll want to normalize your data i.e. store the IDs in a separate array and transform the array of objects into an object with keys as ID.
Example from Normalizr
[{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}, {
id: 2,
title: 'Other Article',
author: {
id: 1,
name: 'Dan'
}
}]
can be normalized to -
{
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 1
},
2: {
id: 2,
title: 'Other Article',
author: 1
}
}
}
}
When your application grows, you'll have multiple reducers and sub-reducers. You'll want to slice a specific portion of your state-tree and so on. For that reason someone might have advised you to store your state in a different manner.
But again, anything works if you make it work! Good luck!

How to change order of array with MongoDB?

I need to be able to increment and decrement the position of an element of an array in a MongoDB object.
I looked at the <update> API in the MongoDB API but could not find anything to let me do so.
I am trying to use findOneAndUpdate through Mongoose and I know the index of the element I am trying to shift up or down.
An example of the array item of base64 encoded images:
{
images: [
"img1",
"img2",
"img3"
]
}
And I would like to move, for example "img2", up or down (but "image" should not be able to pushed up since there is nowhere to go).
If I wanted to push "img2" up then the result would be:
{
images: [
"img2",
"img1",
"img3"
]
}
It doesn't matter if I achieve this through changing the index, swapping, or pushing up/down.
Like #blakes-seven said, you have two ways to do it:
Grabing, updating and pushing
db.images.find({ _id: '' }, { images : 1 })
.then(function(img) {
var tmpImg = img.images[0];
img.images[0] = img.images[1];
img.images[1] = tmpImg;
db.images.update({ _id: img._id }, { $set: { images: img.images } });
})
Updating directly (if you have the image on the client and know the indexes), using $position
db.images.update({ _id: '' }, { $push: { images: { $each: ['img2'] }, $position: 0 } } } )
.then(function() {
db.images.update({ _id: '' }, {$unset: {'images.2': 1}})
});
https://docs.mongodb.org/manual/reference/operator/update/position/
However, I think you should redesign the way you stores your images, using by example a virtual ordering:
{
images: [
{ base64: 'img1', order: 0, _id: 'img1' },
{ base64: 'img2', order: 1, _id: 'img2' },
{ base64: 'img3', order: 2, _id: 'img3' }
]
}
This way, you could order your images using a virtual order index, updating them using only the _id, or updating the whole collection by changing order of all img2, dropping or replacing an image, etc.

How to parse below JSON

How to parse below JSON code in JavaScript where iterators are not identical?
var js= {
'7413_7765': {
availableColorIds: [ '100', '200' ],
listPrice: '$69.00',
marketingMessage: '',
prdId: '7413_7765',
prdName: 'DV by Dolce Vita Archer Sandal',
rating: 0,
salePrice: '$59.99',
styleId: '7765'
},
'0417_2898': {
availableColorIds: [ '249', '203' ],
listPrice: '$24.95',
marketingMessage: '',
prdId: '0417_2898',
prdName: 'AEO Embossed Flip-Flop',
rating: 4.5,
salePrice: '$19.99',
styleId: '2898'
},
prod6169041: {
availableColorIds: [ '001', '013', '800' ],
listPrice: '$89.95',
marketingMessage: '',
prdId: 'prod6169041',
prdName: 'Birkenstock Gizeh Sandal',
rating: 5,
salePrice: '$79.99',
styleId: '7730'
}
}
How can I parse this JSON in JavaScript? I want the values of prdName, listprice, salePrice in JavaScript?
var products = js; // more semantic
for (productId in products){
var product = products[productId];
console.log (product.prdName , product.listprice, product.salePrice);
}
js is an Object, the for (key in instance) iteration moves through the first level object's attributes, in this case 7413_7765, 0417_2898 and prod6169041, this keys are stored in the var productId, so products[productId] will return the value of this attributes.
Note that the "" in object keynames are not necesary.
You have already assigned the JSON to an object js.
You're trying to loop through JavaScript object, as Edorka mentioned iterate it.

Categories