Aaron Reese
Aaron Reese

Reputation: 554

vue js find an object in an array and then spread it into a new array with extra properties

I have three arrays: colour objects, size objects, sku objects. These are fetched from the database using an API call and stored in the Vue data(). I then build a 2D matrix of the sizes and colours with the sku if it exists using the map and find operators

this.sizes.map(
    size=> this.colours.map(
        colour=>(
            this.skus.find(
                sku=> sku.sku == this.style.name + colour.colour_code + size.code
            ) || {sku: this.style.name + colour.colour_code + size.code, selected:false}
        )
    )
 )

I need to assign the results to a new array (this.matrix), however for the UI I also need an additional field (selected:false) that is not in the sku object it does not need to live on the database as it is only for state control. To do this I think I need to use Object.assign({selected:false}, sku) but I can't work out where I would put it in the above code. I have to do it as the this.matrix is assigned, otherwise Vue will not generate the getters and setters

Each cell reference in the 2D array will have 0 or 1 skus in the sku array. Every sku in the sku array will have a corresponding slot in the 2D array.

Where would I put the Object.assign, or is there a better way?

Upvotes: 0

Views: 1255

Answers (3)

Aaron Reese
Aaron Reese

Reputation: 554

Starting to get OT now, Each object in the 2D array MUST have the 'sku' property so it needs to exist in the target array, just in case the source array is NULL. The code may be more readable if I stick in in a variable and then call the variable twice, but it is doing the same logic.

this.sizes.map(
    size=> this.colours.map(
        colour=>(
            skuCode=this.style.name + colour.colour_code + size.code;
            Object.assign(
                {
                   sku: skuCode,
                   selected: false
                },
                this.skus.find(
                    sku=> sku.sku == skuCode
                )
             ) 
         )
     )
 )

Upvotes: 0

Aaron Reese
Aaron Reese

Reputation: 554

This was my solution:

this.sizes.map(
    size=> this.colours.map(
        colour=>(
            Object.assign(
                {
                   sku: this.style.name + colour.colour_code + size.code,
                   selected: false
                },
                this.skus.find(
                    sku=> sku.sku == this.style.name + colour.colour_code + size.code
                )
             ) 
         )
     )
 )

This is now creating a new object with sku and selected and if it finds a matching sku object then spreading the properties (via the Object.assign) into a new object. the sku property exists in both source objects but will only be output once.

Upvotes: 1

Alex Pakka
Alex Pakka

Reputation: 9706

I will simplify it a little, as your question is not really related to VueJS.

let sizes = [1,2,3];
let cols = ['a','b','c']
let sku = ['1.a', '2.c'];

sizes.map( 
   s => cols.map( 
      c => s+"."+c ).map( 
           x => ({sku: x, 
                 selected: sku.find(s => s === x) ? true : false})))
//result is 
//[ 
//  [ {sku: "1.a", selected: true}, {sku: "1.b", selected: false} ...],
//  [ ... ],
//  [ ....] 
//]   

i.e. chain another map to arrive at sku representation and then map to the resulting object. You can then assign the result to your 2D matrix of objects.

If your matrix is quite big and you don't want to re-create a new object for every cell in the matrix, you can use the fact that map provides index as a second optional arrow-function parameter: sized.map( (s,i) => cols.map( (c,j) => { ... } . The code will be less readable, but you could manipulate your matrix directly.

Upvotes: 1

Related Questions