I have a javascript function that passes an object that contains multiple other objects, e.g.
createButtons({
normalButtons: {
button: {
type: 'website',
name: 'Website',
}
}
socialButtons: {
socialButton: {
type: 'fb-share',
name: 'Share on Facebook'
},
socialButton: {
type: 'copyUrl',
name: 'Copy Link'
}
}
});
Now i want to iterate through all the socialButtons, but when I do using a for ... in loop, it only seems to get the first item
function createButtons(options) {
for (x in options.socialButtons) {
console.log(options.socialButtons[x]);
}
}
It only logs 1 object, the Facebook one.
Am I doing something wrong or is there a better way to solve this, please let me know.
Thank you!
You are successfully looping over the properties of that object. The problem is that you only have one property.
You defined a value for socialButton and then you defined another value for socialButton.
You need to make your property names unique.
Better yet: use an array.
Your object will not gonna work as both of the items in socialButtons: have this same keys, so, the first button will be replaced with second.
I recommend changing second socialButton to socialButton2 and everything should work.
You are using same property name socialButton inside socialButtons object. This is the cause of your problem.
Changing the name name socialButton to an unique property name will help you achieving what you want.
Related
I'm trying to render a table using data from an array of objects. These have been created with a constructor which has a number of prototype methods. All the methods work correctly outside of the specific problem I'm having.
The table needs to be rendered dynamically, eventually with user input selecting which columns they want rendered and in which order. As such I'm trying to use a separate array to house the selected fields (filled in manually for now).
Below I have an example of the object, the prototype, the array, and the array of objects forEach method containing a simple console.log.
const jsonResultTotal = {
new_stats: [
{
revenue: 'US$200.00',
cost: 'US$4.09',
}]
};
jsonResultTotal.prototype = {
...jsonResultTotal.prototype,
roas: function() {
return (Number(this.revenue.replace(/[^0-9.]/g, '')) / Number(this.cost.replace(/[^0-9.]/g,''))).toFixed(
2);
},
const rowCellContent = [
'revenue',
'cost',
roas(),
'roas()'
roas
'roas'
];
jsonResultTotal.new_stats.forEach(function(e) {
for (i=0; i<=5;i++){
console.log(e[rowCellContent[i]])
}
}
The result of the above code is
'US$200.00'
'US$4.09'
undefined
Well, actually that specific rowCellContent array will result in roas() is not defined, but the point is that none of the methods will work.
If I console.log(e.roas()) then it works, so accessing the method seems to be fine. I've tried arrow functions in the rowCellContent array, as well as full functions with a return of this.roas(), I've tried to used bind on the e[rowCellContent[i]]
There doesn't seem to be any issues calling the properties through the array, or calling the prototype methods directly, I just can't get the methods via the array to work.
Any help would be appreciated.
So I need to edit a property of an object in javascript. It contains multiple of the same object name. I am fairly familiar with javascript. My object looks like this:
var object = {
Sub: {
name: "FirstSubName",
propertyToChange: "Keep me the same"
},
Sub: {
name: "SecondSubName",
propertyToChange: "Change me" //This is the property I need to change
}
}
I want to change the second property of the second "Sub" to "ChangedProperty". If I want to do it without using chronological order (like object.Sub[1].propertyToChange = "ChangedProperty", what would I do?
As Bergi said, you cannot have these two properties. What you can have is an array, like this:
var object = {
Sub:[{name: "X", prop: "a property"},{name: "Y", prop: "another prop"}]
}
So, you can access them with the array notation you used in your question or either using a forEach for comparing values, for instance.
Hope this helps.
I try to do something like this:
var obj = {id: id, items: "asdf", items: "sdff", test: varTest};
BUT I need to add the two same named items called 'items' dynamically. Because it won't be always the same number of these elements. How can I add them to this object, without overwriting them itselfs?
Thank you very much.
PS: I know that this is probably not a good idea, but I use an API so I can't change this. I need to give them the same name.
You cannot use same key multiple times in an object. You can use array.
var obj = {id: id, items:["asdf", "sdff"], test: varTest};
This will be easy to access the elements having same semantics.
To add items use,
if (obj.hasOwnProperty(items)) {
obj.items.push(newVal);
} else {
obj.items = [newVal];
}
I have an object array:
user :[
{
name: String,
username: String
}
]
I want to view every change either to name or username.
I found underscore _.pluck only does the trick for one property (_.pluck(user, 'name')
Is there another way to have the list of both values?
With pluck you can only use one property, it simply isn't made to retrieve multiple. The method you would want to use is map, as suggested in this relevant question + answer: How to pluck multiple attributes from a Backbone collection?
Assuming you want the following output [['nameA','usernameA'],['nameB','usernameB'],...]], you could use map in the following manner:
var myResult = users.map(function(user) {
return [user.name, user.username];
});
NOTE: I changed the variable user to users to make more sense with your data.
This is a fairly common question here in SO, and I've looked into quite a few of them before deciding to ask this question.
I have a function, hereby called CheckObjectConsistency which receives a single parameter, an object of the following syntax:
objEntry:
{
objCheck: anotherObject,
properties: [
{
//PropertyValue: (integer,string,double,whatever), //this won't work.
PropertyName: string,
ifDefined: function,
ifUndefined: function
}
,...
]
}
What this function does is... considering the given parameter is correctly designed, it gets the objCheck contained within it (var chk = objEntry.objCheck;), It then procedes to check if it contains the properties contained in this collection.
Like this
for(x=0;x<=properties.length;x++){
if(objCheck.hasOwnProperty(properties[x].PropertyName)){
properties[x].ifDefined();
}
else{
properties[x].ifUndefined();
}
What I want is... I want to bring it to yet another level of dynamicity: Given the propositions that IfDefined and IfUndefined are functions to be called, respectively, if the currently-pointed PropertyName exists, and otherwise, I want to call these functions while providing them, as parameters, the very objCheck.PropertyName's value, so that it can be treated before returning to the user.
I'll give a usage example:
I will feed this function an object I received from an external provider (say, a foreign JSON-returning-WebService) from which I know a few properties that may or may not be defined.
For example, this object can be either:
var userData1 = {
userID : 1
userName: "JoffreyBaratheon",
cargo: "King",
age: 12,
motherID : 2,
//fatherID: 5,--Not defined
Status: Alive
}
or
var userData2 = {
userID :
userName: "Gendry",
cargo: "Forger Apprentice",
//age: 35, -- Not Defined
//motherID: 4,-- Not Defined
fatherID: 3,
Status: Alive
}
My function will receive:
var objEntry=
{
objCheck: userData1,
properties: [
{
PropertyName: "age",
ifDefined: function(val){alert("He/she has an age defined, it's "+val+" !");},
ifUndefined: function(){alert("He/she does not have an age defined, so we're assuming 20.");},
},
{
PropertyName: "fatherID",
ifDefined: function(val){alert("He/she has a known father, his ID is "+val+" !");},
ifUndefined: function(){alert("Oh, phooey, we don't (blink!blink!) know who his father is!");},
}
]
}
CheckObjectConsistency(objEntry); // Will alert twice, saying that Joffrey's age is 12, and that his father is supposedly unknown.
ifDefined will only actually work if, instead of properties[x].ifDefined();, I somehow provide it with properties[x].ifDefined(PropertyValue);. And here, at last, lies my question.
Being inside the consistency-checking-function, I only know a given property's name if it's provided. Being inside it, I can't simply call it's value, since there is no such function as properties[x].ifUndefined(properties[x].GetValueFromProperty(properties[x].PropertyName)) ,... is there?
I'm sorry. Not being a native english speaker (I'm brazilian), I can't properly express my doubts in a short way, so I prefer to take my time writing a long text, in an (hopefully not wasted) attempt to make it clearer.
If, even so, my doubt is unclear, please let me know.
I think you're looking for the bracket notation here. It allows you to provide an arbitrary value as key to access the object. Also, you know its name. You have your properties object right?
objEntry.properties.forEach(function(property){
// Check if objCheck has a property with name given by PropertyName
if(!objEntry.objCheck.hasOwnProperty(property.PropertyName)){
// If it doesn't, call isUndefined
property.isUndefined();
} else {
// If it does, call isDefined and passing it the value
// Note the bracket notation, allowing us to provide an arbitrary key
// provided by a variable value to access objCheck which in this case is
// the value of PropertyName
property.isDefined(objEntry.objCheck[property.PropertyName]);
}
});
Oh yeah, forEach is a method of arrays which allows you to loop over them. You can still do the same with regular loops though.