-1

I think I have a problem understanding how javascript or more precisely vuejs in this case works...

the following code is given:

....
data() {
   campaigns: [{id: 1, name: 'Campaign 1'}, {id: 2, name: 'Campaign 1'}]
   campaignsWithEventSettings: [0, 1] //these are the indexes for campaigns
},

methods: {
   saveOrUpdate() {
     let campaigns = [];

     this.campaignsWithEventSettings.map(x => {
          let campaign = this.campaignsSettings[x];
          campaign.event_settings = true;
          console.log(this.campaigns[x].id) //screenshot with the result is attached below 
          campaign.id = this.campaigns[x].id;
          campaigns.push(campaign);
     });
            
     //that gives the same result 
     /*for (let i = 0; i < this.campaignsWithEventSettings.length; i++) {
          let idx = this.campaignsWithEventSettings[i];
          let campaign = this.campaignsSettings[idx];
          campaign.event_settings = true;
          campaign.id = this.campaigns[idx].id;
          campaigns.push(campaign);
     }*/

     let settings = [];
     settings.push({eventId: this.eventId});
     settings.push({campaigns: campaigns});

     axios.post('/events/campaigns', settings).then(resp => {
          console.log(resp)
     })
  },
}

....

the problem is that in the end, all campaigns have the same id, although when running console.log the log ids are different/correct. so in other words at each loop, all campaigns in the array receive a new id (the last one).

console.log screenshot_console

request screenshot_request_data

svtl
  • 3
  • 2
  • We'd need more information to know for sure, but it sounds like you've probably stored the **same object** in multiple properties on `this.campaignsSettings`, so whenever you do `campaign.id = ...`, it updates that **one** object. You're probably doing something **similar** to [this](https://stackoverflow.com/questions/43294552/array-fill-gives-same-object-repeated-why/43294613#43294613) though obviously not quite the same. – T.J. Crowder Feb 09 '21 at 15:27
  • Side note: Don't use `map` if you're not going to use the array it creates and returns. [Here's how to loop through an array](https://stackoverflow.com/questions/9329446/for-each-over-an-array-in-javascript/9329476#9329476). – T.J. Crowder Feb 09 '21 at 15:28
  • hi T.J., thanks for the reply. I edited the post to be more detailed – svtl Feb 09 '21 at 15:49
  • The update still doesn't show us anything about `campaignsSettings`, the thing I called out in my note above. We need to see what it is and how it's populated. Again, it looks like you're putting the same object in it multiple times. – T.J. Crowder Feb 09 '21 at 16:06
  • ah sorry, I missed that. `campaignsSettings` is exactly like `campaigns`, only that the campaign elements in the array are initially with the value `null`, like that: `campaignsSettings: [{id: null, name: null}, {id: null, name: null}]`. this is so because I want to keep the initial values ​​in the `campaigns` array, and when I click on a campaign in a table I can set new values ​​for this campaign that are saved in `campaignsSettings`. and the connection between them is made with the help of the indexes in the `campaignsWithEventSettings`. I hope that makes sense for you. – svtl Feb 09 '21 at 16:21

2 Answers2

1

so I will quote what the problem is and I put the link with more detailed information.

When you use a variable that is declared outside the scope the variable is going to be used in, it will use the value that variable has at the time it runs. It doesn't get a copy of the value at the time the closure is setup. If you think of closures as pointers rather than values, maybe that will help.

sorce: https://dzone.com/articles/why-does-javascript-loop-only-use-last-value

this means that the variable that your let campaign = this.campaignsSettings[x]; is using is always the last one of the X. Because your X is the variable out of the scope, this is very often when you try to output the index of an loop.

A quick solution is to wrap in a function!

for(let x of this.campaignsWithEventSettings){
  (function (newX){
    let campaign = this.campaignsSettings[newX];
    campaign.event_settings = true;
    campaign.id = this.campaigns[newX].id;
    campaigns.push(campaign);
  })(x);
}

or something like

for(let x of this.campaignsWithEventSettings){
  try{throw x}
  catch(newX){
    let campaign = this.campaignsSettings[newX];
    campaign.event_settings = true;
    console.log(this.campaigns[newX].id)
    campaign.id = this.campaigns[newX].id;
    campaigns.push(campaign);
  }
}
Vanishdark
  • 140
  • 11
0

I'd do the following:

 let campaigns = this.campaignsWithEventSettings.map(x => {
      let campaign = this.campaignsSettings[x];
      campaign.event_settings = true;
      campaign.id = this.campaigns[x].id;
      return campaign
 });
Eneas Marín
  • 158
  • 1
  • 5
  • While this is better than using `map` without using its result, if the OP's code doesn't work, this code won't work. Unfortunately, the OP hasn't added the information we need to answer the questnio to the question, despite repeated requests for it. – T.J. Crowder Feb 09 '21 at 16:37