Modifying one instance of an object will automatically alter the other instance as well

Currently, I am working on developing a simple table in Angular where specific functions are applied to modify the table based on different conditions. These include sorting the data upon pressing the sort button and adding salutations based on the gender.

For this project, the data is static and stored in a TypeScript object. Below is the data object being used in the table:

let employeesArray: Employee[] = [
{name: "mike", salary: 100, gender: "M"},
{name: "jason", salary: 400, gender: "M"},
{name: "robin", salary: 9000, gender: "M"},
{name: "beast", salary: 5000, gender: "M"},
{name: "jimmy", salary: 3000, gender: "M"},
{name: "morris", salary: 2000, gender: "M"}
];

export default employeesArray;

The following Angular code displays the table data:

<tr *ngFor="let employee of employeesArray">

<td>{{employee.name}}</td>
<td>{{employee.salary}}</td>
<td *ngIf="showGender;">{{employee.gender}}</td>
</tr>

Additionally, a button has been added to add salutations based on gender:


<button type="button" (click)="addSalutation()" class="btn btn-success mx-2">Add Salutation</button>

However, upon pressing the salutation button, it should revert the salutation addition in the data. Below is the implementation of the addSalutation function:


import employeesArray from '../Employees';
employees: Employee[] = [...employeesArray];
employeesTemp: Employee[] = [...employeesArray];
addSalutation(){

  if(this.showSalutation){
    this.showSalutation=false;
    
    this.employees = employeesArray;
    console.log("Temporary array in true:");
    console.log(this.employeesTemp);
    
  }
  else{

    this.showSalutation=true;
    this.employees = this.employees.filter((employee) => {
    if(employee.gender === "M"){

      employee.name = "Mr." + employee.name;
    }
    else{
      employee.name = "Ms." + employee.name;
    }
    return employee;


  });

   console.log("Temporary array in false:");
   console.log(this.employeesTemp);
  }

Two separate copies of the data are being used so that changes can be reverted by copying data from one set to another upon button press. However, changes made in employees also reflect in employeesTemp, causing confusion.

The console.log() output within the function can be viewed here: https://i.sstatic.net/A4KVju8J.png

The goal is to ensure that no changes occur in employeesTemp so that reversions can be easily made. This issue needs further investigation.

Answer №1

It turned out that the issue was caused by me creating a shallow copy of the object rather than a deep copy.

Instead of the initial code:

empsArray:Employee[]=[...empsArrayImport];
empsTemp:Employee[]=[...empsArrayImport];

I made a change to use:

empsArray:Employee[]=JSON.parse(JSON.stringify(empsArrayImport));
empsTemp:Employee[]=JSON.parse(JSON.stringify(empsArrayImport));

After implementing this change, the problem was fixed.

Answer №2

To efficiently handle deep copying with a modern approach in 2022, you can utilize the structuredClone() function.

empsArray: Employee[] = structuredClone(empsArrayImport);
empsTemp: Employee[] = structuredClone(empsArrayImport);

Performance: The internal algorithm of structuredClone() makes it a faster option.

Safety: Unlike JSON.parse(JSON.stringify(...)), structuredClone() can handle all data types except Symbol. JSON.parse(JSON.stringify(...)) fails with functions, undefined, Date objects, Map, Set, Infinity, NaN, BigInt, RegExp, circular references, etc.

Here’s an example of cloning an object containing a Date type:

const t = { d: new Date() };
console.log(t); // { d: Tue Jul 30 2024 11:04:55 GMT+0200 (Central European Summer Time) }

const tt = JSON.parse(JSON.stringify(t));
console.log(tt); // { d: '2024-07-30T09:04:55.599Z' }

const ttt = structuredClone(t);
console.log(ttt); // { d: Tue Jul 30 2024 11:04:55 GMT+0200 (Central European Summer Time) }

You can find the full compatibility table here: structuredClone() Browser Compatibility

Answer №3

Please take note:

Direct usage is permitted

const employees:Employee[]=[
   {name:"Mike",salary:100,gender:"Male"},
   {name:"Jason",salary:400,gender:"Male"},
   ...
]

Note: it is recommended to use (filter instead)

  this.employees=[...employees].map((emp)=>(
     {...emp,
      name: emp.gender==="Male" ? "Mr. "+emp.name : "Ms. "+emp.name
     }))

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the features of NextJS version 13 with the benefits

Starting from the 13th step, SSR is utilized by default and in order to opt for client side rendering you must specify it at the top like so: 'use client' Currently, my setup involves TypeScript and styled-component integration. Take a look at ...

What causes an array to accumulate duplicate objects when they are added in a loop?

I am currently developing a calendar application using ExpressJS and TypeScript. Within this project, I have implemented a function that manages recurring events and returns an array of events for a specific month upon request. let response: TEventResponse ...

An issue has been encountered at the header component of an Angular web application, identified as error code

I recently created a small Angular web application and decided to create a Header component using the command line ng g c Header. https://i.sstatic.net/ZgCi0.pngI then proceeded to write a brief paragraph in the header.component.html file. <p>header ...

Tips for adjusting the size of icons in Ionic Framework v4 and Angular 7

The library ngx-skycons offers a variety of icons for use in projects. If you're interested, check out the demo here. I'm currently incorporating this icon library into an Ionic project that utilizes Angular. While the icons work perfectly, I&ap ...

Vue defineProps allows for the definition of complex types for properties

Within my code, I am exploring the use of complex prop types in certain instances. Below is an example of what I have in mind: enum Country { [...] } interface IPerson { firstname: string; lastname: string; } interface IAddress { street: string; ...

Utilize the power of generics with Angular's service providers

Is it possible to make the membervar of class Parent generic instead of type any, while still retaining the ability to switch provider classes without having to update all components that rely on class Parent? For example, if class ChildB implements a diff ...

What's the most efficient way to define the type of an object in TypeScript when one of its properties shares the same name as the type itself?

I'm currently working on processing an event payload where the event field is a string, and the content of data depends on the value of the event field. While I have come up with a representation that functions correctly, I can't help but feel th ...

Develop a module using the Angular plugin within the Eclipse IDE

I am currently new to Angular and following the Angular Get Started Tutorial (https://angular.io/guide/quickstart). I am using the angular cli plugin in Eclipse. As I reached the 7th part of the tutorial, I am required to create a new module with the comm ...

I'm looking to send a response with data using Nest JS API and Postman. How can I accomplish this

As I work on setting up my server using Nest Js, I encountered an issue while trying to fetch data from Postman to test the API urls. Unfortunately, I keep receiving empty responses from the server or undefined values from the postman request. Below is a s ...

Finding the specific type within a union based on its field type

I am trying to implement a function sendCommand that returns a value of type specified by the union InputActions, selected based on the action_id type. Below is my code snippet: interface OutputAction1 { command: 'start', params: string; } i ...

What are the suitable scenarios for employing a resolve function to fetch data?

I have a question about when to use a resolver versus simply fetching data when a page is first opened. In an app that I'm working on, different developers used code in routes to look up data before opening the actual form like this: { path: &apos ...

Encountering the 'Default setting for timestampsInSnapshots now set to true' error in Firestore console

Encountering a Firestore error in the console while using Angular. @firebase/firestore: Firestore (5.8.3): The timestampsInSnapshots setting now defaults to true and does not require explicit setting. It is advised to remove it from firestore.settings( ...

A step-by-step guide on injecting dependencies manually in NestJS

When working with Angular, it is possible to access and inject dependencies manually using the built-in Injector class. This allows you to access and inject services without having to pass them through the constructor. Essentially, you can inject a service ...

having trouble retrieving information from mongodb

Currently working with nestjs and trying to retrieve data from a collection based on the 'name' value. However, the output I am getting looks like this: https://i.stack.imgur.com/q5Vow.png Here is the service code: async findByName(name):Promi ...

Angular and Firestore, when combined, present a unique challenge as the queries

After upgrading the code of an outdated project to the latest versions of Angular and RxJs, I made every effort to update the code as thoroughly as possible. Here is a link to my previous code However, I am now encountering the issue of receiving undefin ...

Deriving values in Typescript based on a subset of a union for conditional typing

Can someone provide assistance with type inference in TypeScript to narrow a union based on a conditional type? Our API validates a set of parameters by normalizing all values for easier processing. One parameter can be either an array of strings or an ar ...

Utilizing shared state in React components through props

Currently, I am utilizing a shared global state in the following manner: interface DashboardProps extends React.Props<Dashboard> { globalState? : GlobalState } export class Dashboard extends React.Component<DashboardProps, any>{ } Withi ...

typescript React-Redux challenge: Boosting Your mapDispatchToProps Skills

I'm having trouble determining the type of my mapDispatchToProps function in the SignInComponent. See the code snippet below: Here is my authAction.ts file: import firebase from 'firebase/app' import { Dispatch } from 'react'; ty ...

Tips for effectively utilizing 'ngModel' alongside a form control name

When a user enters or inserts a value into one textarea, I want it to automatically update the other textarea field as well. I thought about using the change function to achieve this, but when I tried to use ng-model with the control name, I encountered a ...

Implement new functionalities within JDL Jhipster for an Angular project

For instance, I am interested in incorporating functions such as onChange, focusout, onBlur, onClick while passing an extra parameter in jdl like this: <input type="text" class="form-control" name="firstName" (onChange)= ...