rishabh kalra
rishabh kalra

Reputation: 35

I am getting the same object inside the for loop for modification in angular

So i want to execute a loop which essentially modifies the structure of element in iteration. But, for modification i have a predefined structure object which i have set as default object. Now while i am looping over each element of the object Array (the array which needs to be modified), i am sending the default object along with current element to some other function which essentially returns a modified object. But, what is happening is that the default object that i am passing along is getting modified after each iteration. How do i stop my default object from getting modified ?

Example, i have this data which i want to modify

[{
    "name": "Sample 1",
    "session_id": "sample_id_1",
    "created": "2020-04-14T06:45:05.494Z",
    "isUploaded": false,
    "username": "username1",
    "topics": [
        {
            "name": "2",
            "isUploaded": true,
            "topic_id": "2"
        },
        {
            "name": "3",
            "isUploaded": true,
            "topic_id": "3"
        }
    ]
},
{
    "name": "Sample_2",
    "session_id": "sample_id_2",
    "created": "2020-04-14T05:43:10.643Z",
    "isUploaded": false,
    "username": "username2",
    "topics": [
        {
            "name": "2",
            "isUploaded": true,
            "topic_id": "2"
        },
        {
            "name": "1",
            "isUploaded": true,
            "topic_id": "1"
        },
        {
            "name": "4",
            "isUploaded": true,
            "topic_id": "4"
        }
    ]
}]

And the default object Array that i want to use is :

[
    {
      topic_id: '1',
      topic_status: '-1',
      topic_name:
      {
        en: 'Some english text 1?',
        hi: 'some hindi text 1?'
      },
      isPlayed: false,
      status: false
    }, {
      topic_id: '2',
      topic_status: '-1',
      topic_name: {
        en: 'some english text 2?',
        hi: 'some hindi text 2?'
      },
      isPlayed: false,
      status: false
    },
    {
      topic_id: '3',
      topic_status: '-1',
      topic_name: {
        en: 'some english text 3?',
        hi: 'some hindi text 3?'
      },
      isPlayed: false,
      status: false
    },
    {
      topic_id: '4',
      topic_status: '-1',
      topic_name: {
        en: 'some english text 4?',
        hi: 'some hindi text 4?'
      },
      isPlayed: false,
      status: false
    }
  ]

Now i have written this loop which will modify each element inside the loop according to the default object as follows:

async getServerSessionsAsLocal(serverSessions) { // serverSessions contains the sample Array of Objects described above
const newArray = [];
const defaultQuestionsForLocal = await this.userService.getUserQuestions(); // this will return the default object Array described above
if (defaultQuestionsForLocal) {
  for (let i = 0 ; i < serverSessions.length; ++i) {
    const generatedSession = this.syncService.generateSession(serverSessions[i], [...defaultQuestionsForLocal]); // this function essentially modifies the serverSession object according to the default object Array
    newArray.push(generatedSession);
  }
}
return [...newArray];

}

So, the function generateSession works as follows : It looks for the topics key inside of the serverSession[i] object supplied (by looping the defaultQuestionsForLocal array) and matches its topic_id with the topic_id present inside the defaultQuestionsForLocal. If there is a match, it updates the topic_status of defaultQuestions element to 3 else keeps it as it is. Now considering that we are modifying the sample Data at index 0 with default QuestionsArray, the resultant generatedSession would look like below :

{
"name": "Sample 1",
"session_id": "sample_id_1",
"created": "2020-04-14T06:45:05.494Z",
"isUploaded": false,
"username": "username1",
"topics": [
    {
        "name": "1",
        "isUploaded": false,
        "topic_id": "1",
        "topic_status": -1
    },
    {
        "name": "2",
        "isUploaded": true,
        "topic_id": "2",
        "topic_status":3,
    },
    {
        "name": "3",
        "isUploaded": true,
        "topic_id": "3",
        "topic_status": 3,
    },
    {
        "name": "4",
        "isUploaded": false,
        "topic_id": "4",
        "topic_status": -1,
    },
]

}

Now the problem that i am facing is , when i pass defaultQuestionsArray to generateSession function, internally it modifies this defaultQuestionsArray, assigns it back to the session object's topics key and return the complete object back. For first iteration, everything seems fine, however for any subsequent iterations, the defaultQuestions Array gets modified. So, after the second iteration, the topic_status key inside each of the elements of defaultQuestions Array would be modified according to the sample object at index 2. So, for example after the second iteration, the defaultQuestionsArray would look like :

[
{
  topic_id: '1',
  topic_status: '3',
  topic_name:
  {
    en: 'Some english text 1?',
    hi: 'some hindi text 1?'
  },
  isPlayed: false,
  status: false
}, {
  topic_id: '2',
  topic_status: '3',
  topic_name: {
    en: 'some english text 2?',
    hi: 'some hindi text 2?'
  },
  isPlayed: false,
  status: false
},
{
  topic_id: '3',
  topic_status: '3',
  topic_name: {
    en: 'some english text 3?',
    hi: 'some hindi text 3?'
  },
  isPlayed: false,
  status: false
},
{
  topic_id: '4',
  topic_status: '3',
  topic_name: {
    en: 'some english text 4?',
    hi: 'some hindi text 4?'
  },
  isPlayed: false,
  status: false
}

]

Note that the 3rd index object is set to 3 as it was modified in the first iteration and the rest were modified in the current iteration. And since i assign this resultant object to the topics key of supplied session object, the previous modified object's topics key also gets the same value. Which means, after second iteration, the newArray would look like :

[{
 "name": "Sample 1",
 "session_id": "sample_id_1",
 "created": "2020-04-14T06:45:05.494Z",
 "isUploaded": false,
 "username": "username1",
 "topics": [
 {
    "name": "1",
    "isUploaded": false,
    "topic_id": "1",
    "topic_status": 3
 },
 {
    "name": "2",
    "isUploaded": true,
    "topic_id": "2",
    "topic_status":3,
 },
 {
    "name": "3",
    "isUploaded": true,
    "topic_id": "3",
    "topic_status": 3,
 },
 {
    "name": "4",
    "isUploaded": false,
    "topic_id": "4",
    "topic_status": 3,
 }
]
}, {
"name": "Sample_2",
"session_id": "sample_id_2",
"created": "2020-04-14T05:43:10.643Z",
"isUploaded": false,
"username": "username2",
"topics": [
    {
        "name": "1",
        "isUploaded": true,
        "topic_id": "1",
        "topic_status": 3
    },
    {
        "name": "2",
        "isUploaded": true,
        "topic_id": "2",
        "topic_status": 3
    },
    {
        "name": "1",
        "isUploaded": true,
        "topic_id": "1",
        "topic_status": 3
    },
    {
        "name": "4",
        "isUploaded": true,
        "topic_id": "4",
        "topic_status": 3
    }
]
}]

What i want is that everyTime i pass the defaultQuestionsArray to the generate session function, it should always be the default Array. Any idea about how to rectify this ?

Upvotes: 0

Views: 416

Answers (1)

Layer
Layer

Reputation: 336

Use:

Object.create(originalTemplateObject);

where you have problems of the original being modified, this method returns a copy of an object and his properties without keeping references, ref:

Object.create

Then you can modify the copy instead of modifyng the original passed by reference.

an example:

so your default object template is something like this:

{
  topic_id: '1',
  topic_status: '-1',
  topic_name:
  {
    en: 'Some english text 1?',
    hi: 'some hindi text 1?'
  },
  isPlayed: false,
  status: false
}

you should save this template outside all of your code, because should be a global constant:

const objectTemplate = {
  topic_id: '',
  topic_status: '',
  topic_name:
  {
    en: '',
    hi: ''
  },
  isPlayed: false,
  status: false
}

Here we have a function that creates the object, and then returns the new object using the passed parameters.

const objectTemplate = {
  topic_id: '',
  topic_status: '',
  topic_name:
  {
    en: '',
    hi: ''
  },
  isPlayed: false,
  status: false
}

const myObjects = [];

function copyObject(...objectValues){

    let i = 0;
    const newObject = Object.create(objectTemplate);
    
    for(let prop in newObject){
       newObject[prop] = objectValues[i];
       i++;
    }

    return newObject;
}

myObjects.push(
  copyObject('1', '-1', {en: 'Some english text 1?',hi: 'some hindi text 1?'}, false, false
));

console.log("array with the object copy: " + "\n");
console.log(myObjects);
console.log("\n" + "original object: " + "\n");
console.log(objectTemplate);

This is an example of how to use this method without modyfing the original object.

Upvotes: 1

Related Questions