1

Having an object of this form:

myObj = {
    id: 1,
    values: {
        internal: {
                myProp1: true
                myProp2: true
            },
        external: {
                myProp1: true
                myProp2: true
            }

    }
};

I want to be able that when I choose an option, internal or external to be able to set myProp1 to false only for the one option I chose.

In this case, if I choose internal the object should look like this:

myObj = {
    id: 1,
    values: {
        internal: {
                myProp1: false
                myProp2: true
            },
        external: {
                myProp1: true
                myProp2: true
            }

    }
};

I tried to do it like but something I do wrong:

    Object.keys(myObj).forEach(element => {
        if(element === "values") {
            element.forEach(innerElement => {
                if(innerElement === "internal") {
                    innerElement.myProp1= false;
                }
            });
        }
    });

Any suggestions?

Leo Messi
  • 5,157
  • 14
  • 63
  • 125
  • you can access subobject like accessing object prop `myObj.values.internal.myProp1 = false` – jonatjano Aug 29 '18 at 14:58
  • 2
    If you want to use a string as a property name, you could use the `[...]` notation, here is an example: `myObj.values[innerElement].myProp1 = false`. You can find more details [HERE](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Bracket_notation) – Titus Aug 29 '18 at 15:00

3 Answers3

2

you can access subobject like accessing object prop

myObj.values.internal.myProp1 = false

Take care it will throw an error it at least one of the element of the chain (except myProp1) is not defined

Like @titus said in comment you can also use the [...] notation

myObj = {
  id: 1,
  values: {
    internal: {
      myProp1: false,
      myProp2: true
    },
    external: {
      myProp1: true,
      myProp2: true
    }
  }
};

// using basic notation
console.log(myObj.values.internal.myProp1)

// using [...] notation to access prop by name
console.log(myObj["values"]["internal"]["myProp1"])

// the [...] notation is generally used when the prop name is in a variable
let propName = "internal"
console.log(myObj["values"][propName]["myProp1"])

// can be mixed
console.log(myObj["values"].internal["myProp1"])
console.log(myObj.values[propName].myProp1)
jonatjano
  • 3,576
  • 1
  • 15
  • 20
0

I think this is what you want. You need to access the variable myObj itself.

Object.keys(myObj).forEach(element=>{
    if(element === "values"){
        Object.keys(myObj[element]).forEach(innerElement=>{
            if (innerElement === "internal"){
                myObj[element][innerElement].myProp1 = false;
            }
        })
    }
})
Wesgur
  • 3,140
  • 3
  • 18
  • 28
0

If you're also taking suggestions, I would advice to use arrays to represent collections instead of objects. That makes the code to find anything inside the array way easier than looping over keys and values.

Smart data structures and dumb code usually work better than the other way. Switching from objects to arrays for collections reduced the code I had to write for transformations by a huge margin.

const collection = [
  {
    "id": 1,
    "internal": [
      { "name": "myProp1", "val": true },
      { "name": "myProp2", "val": true }
    ],
    "external": [
      { "name": "myProp1", "val": true },
      { "name": "myProp2", "val": true }
    ]
  },
  {
    "id": 2,
    "internal": [
      { "name": "myProp1", "val": false },
      { "name": "myProp2", "val": false }
    ],
    "external": [
      { "name": "myProp1", "val": null },
      { "name": "myProp2", "val": null }
    ]
  }
];
const item_1 = collection.find( item => item.id === 1 );
const internal_prop = item_1.internal.find( prop => prop.name === 'myProp1' );
internal_prop.val = false;
console.log( collection );
Shilly
  • 8,511
  • 1
  • 18
  • 24