senty
senty

Reputation: 12857

Deeply nested data objects in multidimensional object

I have a multidimensional object and using Vue, I am trying to make the inner object reactive.

My object looks like this:

data() {
   return {
       myObject: {}
   }
}

And the filled data looks like this:

myObject: {
   1: {         // (client)
     0: "X",    // (index) : (value)
     1: "Y"
   },
   2: {
     0: "A",
     2: "B"
   }
}

If I try using:

let value = "X";
let client = 1;
let index = 1;

let obj = {};
obj[client][index] = value;
this.myObject = Object.assign({}, this.myObject, obj);

It throws an error:

TypeError: Cannot set property '0' of undefined

And if I try below, it overwrites the initial values as it is initially setting the object to {}

let obj = {};
obj[index] = value;
let parentObj = {};
parentObj[client] = obj;
this.myObject = Object.assign({}, this.myObject, parentObj);

What is the proper way of adding the values to the multidimensional object?

Upvotes: 0

Views: 831

Answers (2)

reinerBa
reinerBa

Reputation: 1660

Just use an array, thats reactive by design. If you need to get elements from the array in your template or anywhere just add a find method

// temp

late
<div v-for="(value, idx) in myArray">{{find(obj => obj.id === idx)}}</div>

methods: {
  find (searchFunction) {
    return this.myArray.find(searchFunction)  
  }
}

Upvotes: 0

Catalyst
Catalyst

Reputation: 3247

In javascript, dim2Thing[1][1] = ... expressions require dim2Thing[1] to exist. This is why you get the error you mentioned. So you can do two expressions, which should work fine:

dim2Thing[1] = dim2Thing[1] || {} dim2Thing[1][1] = otherThing

For the last block, you mention that it "overwrites the initial values"

I think what's actually happening here is just that Object.assign is not recursive. It only merges top-level keys. So if parentObj has a key that over-laps with this.myObj, then sub-keys will be lost.

Object.assign({ a: { b: 2} }, { a: { c: 3 } }) // returns { a: { c: 3 }  }

This is what I interpret your code as trying to do - though I am unfamiliar with vue.js at this time, so I cannot assure it will have the desired result to your webpage:

let value = "X";
let client = 1;
let index = 1;

const newObj = Object.assign({}, this.myObject);
// if you have lodash _.set is handy
newObj[client] = newObj[client] || {}; // whatever was there, or a new object
newObj[client][index] = value
this.myObject = newObj

Upvotes: 1

Related Questions