How to use for/in loop to transfer object properties? - javascript

I have an object that's nested like the example below.
var posts = {
"post1": {
"slug": "slug1",
"title": "title1",
},
"post2": {
"slug": "slug2",
"title": "title2",
}
};
I'm trying to write a for/in loop that will allow me to iterate through this object.
var testLoop = function () {
for (var prop in posts){
post = prop;
console.log(post); // Outputs post1 and post2
console.log(post.slug); // Outputs undefined
}
}
As seen above, I can't store and later access the properties of each iterated object. Only the name of the object is stored and logged. When I run typeof, I see that it's not even an object, it's just a string.
How can I correctly store each iterated properties as objects (post1, post2 etc.) during the loop so I can access their properties using dot notation?

When you use
for (var prop in posts){ ... }
It loops over the string keys in the posts object.
The main point here is that prop will be a string, and not an object like your current code is expecting.
As users in the comments suggested, because prop is the object key as a string, you need to use posts[prop] to refer to the actual object.
Here is some updated code.
var testLoop = function () {
for (var prop in posts){
post = posts[prop]; // ** this is line that needs to be modified **
console.log(post); // Outputs post object
console.log(post.slug); // this should work now
}
}

Related

QML Javascript Dictionary of Property Alias not Updating

My question is the following:
Do changes to the javascript dictionary values not modify the actual value that is mapped, but rather its own internal copy? Is there a way to get around this?
I have a javascript dictionary that contains property aliases of an object.
When I assign them values, the objects in the dictionary itself changes but it does not propagate outward to the actual display that I want to change.
I have had this problem before, placing the dot access outside of the dictionary access fixed it. However, I cannot do it this time around due to the fact that you cannot dot access using .text because it produces error of cannot read property of undefined.
QML: Cannot read property 'xxx' of undefined
My code resembles something of the following example, I had it obscured to protect actual info so sorry if it is a cringy example.
onUpdate passes in another dictionary that I want to tie to the local .qml dictionary.
ControllerDisplay.qml
// ...
property alias id1: id_box.text
// ...
SomeBox
{
id: id_box
text: "some text"
}
main.qml
ControllerDisplay{
id: controller
}
// ...
Connections
{
target: myguimodel
onUpdate:
{
var dict = { "ID1" : controller.id1}
for (var key in updates)
{
dict[key] = updates[key] // does NOT change the value in ControllerDisplay
controller.id1 = updates[key] // DOES change the value ControllerDisplay
}
}
}
When you do var dict = { "ID1" : controller.id1}, you store the value of controller.id1, not a reference to it.
If you want to be able to modify it you could do:
var dict = { "ID1": { "object": controller, "property": "id1"}};
for (var key in updates) {
var target = dict[key];
target.object[target.property] = updates[key];
}
This whole code doesn't look really QML idiomatic though. I would try using property binding if I were you.

How to grab the children of an Object.keys(myEl) reference

In the code below, I can get a reference to the text000 object, but I need to capture its child array as my target payload. Once I have a reference to the key, how can I capture its children?
Full object is below:
activeItem = [{"dnd":{"index":0,"active":true,"group":"common","label":"Text (000)","type":"text"},
"json":{"schema":{"properties":{"text000":{"title":"Text (000)","type":"string"}},"required":["text000"]},"layout":[{"key":"text000","description":"","floatLabel":"auto","validationMessages":{"required":"Required"}}]}}]
To grab a reference to the "text000" key I'm using:
const myEl = Object.keys(this.activeItem.json.schema.properties); // points to text000
I need to pull that key's contents/children > {"title":"Text (000)","type":"string"} out to use it as my target payload for this operation.
The text000 element is dynamic so I need its reference, which is why I'm using the Object.keys() method to point to it.
Feel free to school me on the proper names to use to refer to these elements. For example, not sure exactly how to reference > {"title":"Text (000)","type":"string"} with respect to the key text000. Is that the key's "children", "value", "contents" or what?
UPDATE:
console.log('TRY: ', this.activeItem.json.schema.properties[0]);
// Returns undefined
console.log('TRY2: ', this.activeItem.json.schema.properties);
// Returns {"text000":{"title":"Text (000)","type":"string"}}
I need something to return:
{"title":"Text (000)","type":"string"}
SOLUTION thanks #jaredgorski:
const properties = this.activeItem.json.schema.properties;
const propertiesKeys = Object.keys(properties);
const propertiesKeysFirstVal = Object.keys(properties)[0];
const logProperties = properties[propertiesKeysFirstVal];
console.log('PROPERTIES KEYS:', propertiesKeys);
console.log(
'VALUES OF FIRST PROPERTIES KEY:',
propertiesKeysFirstVal
);
console.log('RESULT:', logProperties);
PROPERTIES KEYS: ["text000"]
wrux-wrux-form-builder.js:1782 VALUES OF FIRST PROPERTIES KEY: text000
wrux-wrux-form-builder.js:1783 RESULT: {title: "Text (000)", type: "string"}
You need to remember that activeItem is an array. As long as you include the index (in this case the first index, which is [0]), you can access the json property (or key) and continue down the chain to retrieve the values in text000.
The other trick here is that you're wanting to access the first key in properties, but you don't know the name of that key yet. So what you need to do is actually make an array of the keys and then find out the name of the first key in that properties object. To do this, you can use Object.keys(), a method which turns the keys of an object into an array. Once you have the name of this key, you only need to use bracket notation on the properties object to find the value for this key. I'll show you how this works in the snippet below.
Here are some references so that you can learn more about how this works:
MDN page on the Object.keys() method
Accessing JavaScript
object properties: Bracket notation vs. Dot notation
And here's the working example:
const activeItem = [
{
"dnd": {
"index": 0,
"active": true,
"group":"common",
"label":"Text (000)",
"type":"text",
"icon":"text_fields",
"fontSet":"material-icons",
"class":""
},
"json": {
"schema": {
"properties": {
"text000":{
"title":"Text (000)",
"type":"string"
}
},
"required":["text000"]
},
"layout":[
{
"key":"text000",
"description":"",
"floatLabel":"auto",
"validationMessages": {
"required":"Required"
}
}
]
}
}
]
// This is the dirty looking version:
const logPropertiesDirty = activeItem[0].json.schema.properties[Object.keys(activeItem[0].json.schema.properties)[0]]
console.log("First, the dirty version where we don't save anything to variables. Everything is laid out here.")
console.log('WHAT WE DID:', 'activeItem[0].json.schema.properties[Object.keys(activeItem[0].json.schema.properties)[0]]')
console.log('RESULT:', logPropertiesDirty)
console.log('=================================================')
// This is the cleaner version, using variables to store things as we go:
const properties = activeItem[0].json.schema.properties;
const propertiesKeys = Object.keys(properties);
const propertiesKeysFirstVal = Object.keys(properties)[0];
const logPropertiesClean = properties[propertiesKeysFirstVal];
console.log('Now, the cleaner version. We save some values to variables to make things more readable.')
console.log('PROPERTIES OBJECT:', properties)
console.log('PROPERTIES KEYS:', propertiesKeys)
console.log('NAME OF FIRST PROPERTIES KEY:', propertiesKeysFirstVal)
console.log('RESULT:', logPropertiesClean)
Regarding what to call these things, I've always thought of Objects as generally consisting of "key-value pairs". Keys can also be called properties and values can also be called contents (I guess).
myObject = {
key1: value1,
property2: contentsOfProperty2
}
At the end of the day, clear communication is all that counts! So, whatever names you come up with (as long as they make reasonable sense), I'm sure people won't be jerks about it unless they feel like they have something to prove.
You should be able to use Object.values over this.activeItem.json.schema.properties:
The Object.values() method returns an array of a given object's own enumerable property values, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]
It is not supported across the map yet, but you should be able to load a polyfill if you need it.

Passing an unknown number of nested object properties into a function [duplicate]

This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 5 years ago.
Not sure if my title describes what I want to do correctly. Basically, I want a function that extracts properties from objects containing objects. I am going to need to loop through various arrays containing many objects of the same class and extract specific values.
myarray1[
0:
object1 = {
objectProp1: {
objectProp1Prop1:"Hello",
objectProp1Prop2:"Goodbye",
objectProp1Prop3:{
objectProp1Prop3Prop1: "Come here",
objectProp1Prop3Prop2: "Go away"
},
},
objectProp2: "Yo",
objectProp3: "Seeya",
}
1:
object2 = { same as object1 but with other property values }
];
myarray2[
0: { different type of object with a different set of nested properties that the function can extract }
1: { idem }
];
function extractProperty(objectArray, property) {
//How do I write this code?
propertyvalue = objectArray.property;
return propertyvalue;
}
extractProperty(myarray1[0], object.objectProp3) = "Seeya"
extractProperty(myarray1[0], object.objectProp1.objectProp1Prop1) = "Hello"
extractProperty(myarray1[0], object.objectProp1.objectProp1Prop3.objectProp1Prop3Prop1) = "Come here"
In the final code the function needs to be able to loop through all the array keys and create an array list containing the chosen property from every object in the original array, but that I can manage. It's the sending of the specific property that needs to be extracted from the objects in the array into the function that I have no idea how to do.
Is there a generalised way to send a "path" of properties into a function and then use it there? How?
Thanks for your help!
Looks like an assignment to me. So I won't give you the code but will explain the approach.
First you need to pass the property names as a string
In your function you need to split the string based on the delimiter, like .
Keep a reference of current object
Then iterate on all the property names that you got from #2
Fetch current property name from current object and replace current object with the returned value.
return current object at the end.
Note: you need to add some validations in between. I've skipped those for you to explore ;)
You could try recursion:
object1 = {
objectProp1: {
objectProp1Prop1:"Hello",
objectProp1Prop2:"Goodbye",
objectProp1Prop3:{
objectProp1Prop3Prop1: "Come here",
objectProp1Prop3Prop2: "Go away"
},
},
objectProp2: "Yo",
objectProp3: "Seeya",
};
object2 = {
objectProp1: 'test1',
objectProp2: 'test2'
}
var myArray = [object1, object2];
function getProp(objArray, prop) {
for(var key in objArray) {
if (key == prop)
return objArray[key];
if (typeof objArray[key] == 'object')
return getProp(objArray[key], prop);
}
}
//test
document.getElementsByTagName('h1')[0].innerHTML = getProp(myArray[0],'objectProp1Prop3Prop1');
I added a Fiddle for you to try it: https://jsfiddle.net/afabbro/vrVAP/

Accessing properties of a variable object with JavaScript

I have a js object that looks like this:
var object = {
"divisions": {
"ocd-division/country:us": {
"name": "United States",
}
}
};
I want to access the property listed under the nested object "ocd-division/country:us" (aka "name"), but the problem I'm having is that "ocd-division/country" is a variable object. Like it might be ":can" for Canada or something.
My question is, can I still access the name property under that object even though it's variable? I wrote the code I came up with below, but it calls the object literally, so it can't account for a change in the object's name.
var country = document.getElementById("p");
p.innerHTML = object.divisions["ocd-division/country:us"].name;
I'm new to JavaScript so I'm sorry if this is a dumb question.
When you don't know the properties of an object, you can use
for...in loop
It iterates enumerable own and enumerable inherited properties.
Object.keys
It returns an array which contains enumerable own properties.
Object.getOwnPropertyNames
It returns an array which contains own properties.
// Adding properties: "ownEnumerable", "ownNonEnumerable",
// "inheritedEnumerable" and "inheritedNonEnumerable"
var obj = Object.defineProperties({}, {
ownEnumerable: {enumerable: true},
ownNonEnumerable: {},
});
Object.defineProperties(Object.prototype, {
inheritedEnumerable: {enumerable: true},
inheritedNonEnumerable: {},
});
// Display results
function log(id, arr) {
document.getElementById(id).textContent = '[' + arr.join(', ') + ']';
}
log('forin', function(forInProps){
for (var prop in obj) forInProps.push(prop);
return forInProps;
}([]));
log('keys', Object.keys(obj));
log('names', Object.getOwnPropertyNames(obj));
<dl>
<dt><code>for...in</code></dt><dd id="forin"></dd>
<dt><code>Object.keys</code></dt><dd id="keys"></dd>
<dt><code>Object.getOwnPropertyNames</code></dt><dd id="names"></dd>
</dl>
object.divisions[Object.keys(object.divisions)[0]].name
Sure...
for (var division in object.divisions) {
var name = object.divisions[division].name;
// Do what you want with name here
}
If the object has prototype methods you will want to use Object.prototype.hasOwnProperty() to ensure they don't get iterated like so:
for (var division in object.divisions) {
if (!object.divisions.hasOwnProperty(division)) continue;
var name = object.divisions[division].name;
// Do what you want with name here
}
Or use Object.keys() if you don't care about IE8 support and iterate over those.
Object.keys(object.divisions).forEach(function(division) {
var name = object.divisions[division].name;
// Do what you want with name here
});
EDIT: Upon re-reading your question it occurs to me that you may already know the key name but want to access the object with a variable key name, which is also absolutely fine:
var division = 'ocd-division/country:us';
object.divisions[division].name;
When using [] bracket notation to access an object you can insert any code that evaluates to a string, you could even call a function in there that returns a string.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors
You can iterate through object using for loop.
var obj = {
"divisions":{
"ocd-division/country:us":{
"name" : "United States"
}
}
}
Here is the for loop
for(var a in obj){ //loop first the object
for(var b in obj[a]){ // then second object (divisions)
for(var c in obj[a][b]){ //then third object (ocd-division/country:us)
if(c == 'name'){ //c is the key of the object which is name
console.log(obj[a][b][c]); //print in console the value of name which is United States.
obj[a][b][c] = "Canada"; //replace the value of name.
var objName = obj[a][b][c]; //or pass it on variable.
}
}
}
}
console.log(obj); //name: Canada
console.log(objName); //name: United States
You can also use this reference:
https://developer.mozilla.org/enUS/docs/Web/JavaScript/Reference/Statements/for
http://stackoverflow.com/questions/8312459/iterate-through-object-properties

Find index of object in array by key

I have an array of objects like so
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
I'm trying to modify one, but I only know its key. I need to pinpoint the item1 object so I can change its value (the values are random and I don't know them, so I can't rely upon them).
If I could just get the index of the item it would be pretty easy: myobj[index].value = "newvalue".
Maybe using the index isn't the best way, so if it isn't, I'm open to other ideas.
I was thinking I could try something like
myobj.objectVar
Where objectVar is the key I'm being passed (item1, for example), however this does not work, possibly because it's a variable? Is it possible to use a variable like this maybe?
If it helps, I'm using underscore.js as well.
Your guess at a solution doesn't work because you're not accessing the individual objects, you're accessing an array of objects, each of which has a single property.
To use the data in the format you've got now, you need to iterate over the outer array until you find the object that contains the key you're after, and then modify its value.
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
function setByKey(key, value) {
myObj.forEach(function (obj) {
// only works if your object's values are truthy
if (obj[key]) {
obj[key] = value;
}
});
}
setByKey('item1', 'new value');
Of course, the far better solution is to stop using an array of single-property objects, and just use one object with multiple properties:
myobj= {"item1" : info in here, "item2" : info in here, "item3" : info in here};
Now, you can simply use myObject.item1 = "some new value" and it will work fine.
You can write a function like,
function getElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
// if the key is present, store the object having the key
// into the array (many objects may have same key in it)
objectsHavingGivenKey.push(individualObject);
}
});
// return the array containing the objects having the keys
return objectsHavingGivenKey;
}
If you only want to get the index of elements having the given key
You can do something like this,
function getIndexesOfElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject, index) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
//push index of element which has the key
objectsHavingGivenKey.push(index);
}
});
// returns the array of element indexes which has the key
return objectsHavingGivenKey;
}
Try this code:
function changeObj( obj, key, newval )
{
for( var i=0, l=obj.length; i<j; i++)
{
if( key in obj[i] )
{
obj[i] = newval;
return;
}
}
}
var myObjArray= [{"item1" : "info in here"},{"item2" : "info in here"}, {"item3" : "info in here"}]
To find and add new value to the object inside an array:
myObjArray.forEach(function(obj) {
for(var key in obj) {
// in case you're matching key & value
if(key === "item1") {
obj[key] = "update value";
// you can even set new property as well
obj.newkey = "New value";
}
}
});
You can access objects the same using their index, even the object inside the original object.
Is this kind of what your looking for:
var otherObj = [{"oitem":"oValue"}];
var myobj= [{"item1" : otherObj},{"item2" : "2"}, {"item3" : "tesT"}];
myobj[0].item1[0].oitem = "newvalue";
alert(myobj[0].item1[0].oitem);

Categories

Resources