Is there a native feature in Vue.js that allows for the addition of a duplicate of a constantly saved object to an array that is repeated

Having an issue with my Vue.js app where adding a newItem to a list of items results in the added object being bound to the input. Here's what I've tried so far:

new Vue({
  el: '#demo',

  data: {
    items: [
      {
        start: '12:15',
        end: '13:15',
        name: 'Whatch Vue.js Laracast',
        description: 'Watched the Laracast series on Vue.js',
        tags: ['learning', 'Vue.js', 'Laracast', 'PHP'],
        note: "Vue.js is really awesome. Thanks Evan You!!!"
      },
      {
        start: '13:15',
        end: '13:30',
        name: "Rubik's Cube",
        description: "Play with my Rubik's Cube",
        tags: ['Logic', 'Puzzle', "Rubik's Cube"],
        note: "Learned a new algorithm."
      }
    ],
    newItem: {start: '', end: '', name: '', description: '', tags: '', note: ''}
  },

  methods: {
    addItem: function(e) {
      e.preventDefault();

      this.items.push(this.newItem);
    }
  }
});

Although pushing the object as is onto the array works, it remains bound to the input causing issues. Desired outcome is to add a copy of the object that won't change when the input does. Check out this this fiddle. One way I found solution is by doing:

addItem: function(e) {
  e.preventDefault();
  this.items.push({
    name:        this.newItem.name,
    start:       this.newItem.start,
    end:         this.newItem.end,
    description: this.newItem.description,
    tags:        this.newItem.tags,
    notes:       this.newItem.notes
  })
}

This alternative method however involves a lot of repetitions.

The main question: Is there any built-in functionality within Vue.js to add just a copy of the object instead of persisting the original object?

Answer №1

Take a look at this particular issue on GitHub.

Surface-Level Replication

I had been utilizing jQuery's $.extend until I learned from Evan You about an unpublicized built-in extend function Vue.util.extend that accomplishes surface-level replication. Here is an example of how you can apply it:

addItem: function(e) {
  e.preventDefault();

  this.items.push(Vue.util.extend({}, this.newItem));
}

View the revised Fiddle for demonstration.

In-Depth Replication

When performing a surface-level clone on an object that contains references to other objects, you are actually duplicating the references to those external objects rather than cloning them. To fully replicate the object, you need an In-Depth Clone.

For an in-depth clone, as Evan mentioned in the initial link, one could utilize:

JSON.parse(JSON.stringify(object))
. This difference can be observed between this fiddle and this fiddle.

If you are using lodash, explore lodash cloneDeep. For NPM users, consider checking out clone-deep.

Answer №2

Unfortunately, this approach did not yield the desired results for my project which utilizes vue 1.0.13. I found a workaround by creating a duplicate of the item without any data bindings like so:

this.items.push( JSON.parse( JSON.stringify( newItem ) ) );

Answer №3

LATEST UPDATE:

To create a clone without object references, consider using structuredClone:

  addItem: function(e) {
    e.preventDefault();
  
    this.items.push(structuredClone(this.newItem));
  }

ANOTHER OPTION:

An alternative approach is to utilize Object Spread:

  addItem: function(e) {
    e.preventDefault();
  
    this.items.push({...this.newItem});
  }

PREVIOUS METHOD:

If you prefer, you can stick with Vanilla JavaScript and Object.assign():

  addItem: function(e) {
    e.preventDefault();

    this.items.push(Object.assign({}, this.newItem));
  }

Answer №4

The answer at the top is inaccurate. Vue.util.extend is not related to jQuery's extend and only performs a shallow clone. Visit here for more information

Object.assign and the Spread operator also result in shallow copies. You can learn more about this here

To achieve a deep clone, consider using Ramda.js' implementation See implementation details here

If you do not require _curry, you can omit it.

For further insights on efficient ways to perform a deep clone of an object in JavaScript, check out this MVA: What is the most efficient way to deep clone an object in JavaScript?

Answer №5

structuredClone is a useful method, but there's a catch. It doesn't work with Proxies, which Vue 3 uses for reactivity. To clone an object using structuredClone in Vue 3, you first need to get the raw target and then clone it like this:

import { toRaw } from 'vue'
...
const copiedObject = structuredClone(toRaw(originalObject))

Answer №6

Implementing lodash library

import _ from 'lodash';


let clonedData = _.cloneDeep(this.formDataInitial);

let mergedData = _.merge(_.cloneDeep(this.formData), { filters: _.cloneDeep(this.formDataInitial.filters) });

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

ES6 scoping confusion: unraveling the mystery

I stumbled upon these two syntax methods for exporting functions. Let's say we have files named actions.js and app.js. The first method looks like this: in actions.js export function addTodo() {} export function deleteTodo() {} and in app.js I have ...

Unable to incorporate an external JavaScript file via a static URL

I'm attempting to link an external javascript file using a static URL, like this: <script type="text/javascript" src="{{ url_for('static/js', filename='test.js') }}"></script> However, I am encountering the following ...

Generating separators in every third row using an array of card elements

https://i.stack.imgur.com/PIMR2.png Hey everyone, I'm working on creating a Divider for every row of 3 items. Currently, my setup only handles two sets of rows, but there could be an unlimited amount of rows that need this divider. I am using slice t ...

Open Zurb Foundation Reveal Modal from the bottom of the screen

Struggling to make the reveal modal open from the bottom of the window. Any assistance would be highly appreciated. I've been attempting to tweak the open function with the reveal js, as seen in the original code below. Thank you, P open : function ...

Ensure that the form is submitted when a checkbox is clicked, while also maintaining the native browser

My form contains a text input field and a checkbox. The text input must not be left empty when the form is submitted, which is why the required attribute is used. I want the form to be submitted every time the checkbox is clicked, while still maintaining ...

Leveraging Angular Dragula without the need for RequireJS

I'm eager to incorporate Drag and Drop functionality into my Angular project with the help of the angular-dragula module (https://github.com/bevacqua/angular-dragula). However, it appears that this module heavily relies on RequireJS. My experience wit ...

Encountering an issue with Meteor and node-celery: "Unable to access property 'slice' of null"

Check out the Github repository for reproducing this issue Run localhost:3000 to replicate the problem. In my setup with Meteor 1.4.4.1, I am utilizing the node-celery npm packages on the server side. Upon Meteor initialization, the client automatically i ...

By incorporating JavaScript, clicking on an image will trigger a shift in the position of a different element

Just starting out with JavaScript and experimenting with creating an event where clicking on an image triggers the movement of another hidden image. The hidden image is positioned off-screen to the left, while there is a table of images in the center of th ...

Effortlessly Display or Conceal Numerous Table Columns Using jQuery

I have a small table where I want to hide certain details with a basic button... for instance, table { border-collapse: collapse; } th, td { border: 1px solid gray; padding: 5px 10px; } <button>Show/Hide Details</button> <table> ...

Can you please provide guidance on how to dynamically add number values from an array to a select tag in Vue.js?

I'm trying to populate a select tag with options from an array variable that contains arrays of number values. However, the values being output appear to be blank. Here is the HTML code: <select required id="dropDown"> <option>Sele ...

The HTTP request is being executed twice for some reason unknown to me

import React, {useState, useEffect} from 'react' export function UseStateExample() { // This is a named export that must be used consistently with {} when importing/exporting. const [resourceType, setResourceType] = useState(null) useEffect ...

JavaScript and PHP are successfully displaying a success message despite the data not being saved to the database

I recently added a new feature to my website where users can submit a form using Javascript without having to reload or refresh the page. This allows for a seamless experience and displays success messages instantly. However, being a newcomer to Javascript ...

Incorporating Java project dependencies into an npm project

I'm facing a challenge in my development process, where I need to incorporate dependencies from a Maven Java project into my package.json file within my Vue/Typescript project. These dependencies are crucial for accessing specific data types that my p ...

What is the best way to hide the input field when there are multiple parent classes present?

I am currently implementing dynamic fields with jQuery and everything is functioning correctly. The problem arises when I attempt to remove these fields. After searching on Google and browsing past questions on StackOverflow, I noticed that everyone seems ...

Is there a way to integrate the javascript and jQuery functions in order to conceal a button?

I recently acquired the File Upload script known as Simple Photo Manager and I am looking to incorporate jQuery functions with the existing JS code in the script. My main goal is to make the Delete button disappear once it has been clicked. However, I am ...

Ways to display additional information in typeahead using Angular JS

Currently, I am using the Bootstrap directory typeahead in Angular. I am looking to display more results in my HTML template instead of just the name: typeahead="job as job.name for job in getJobPlace($viewValue) | filter:{name:$viewValue}" I would like ...

Check out the ViewUI Vue.js component that expands to reveal more content!

Is there a simple component to create the expand/collapse button with a blur effect like in all the demos? I see it used across different variations of the demos and am wondering if there is a specific component or demo showcasing how to achieve this effec ...

Ways to retrieve information from a URL using the .get() method in a secure HTTPS connection

As I work on handling user input from a form using node.js, express, and bodyParser, I encounter an issue. Even after using console.log(req.body), the output is {}. This is puzzling as there is data in the URL when the form is submitted successfully at htt ...

Inserting a file read using Node.js into a MongoDB database

Recently, I came across a text file that contains the following data: title: A, alert: notice, desc: Starting title: B, alert: notice, desc: Process Step 1 and 2 Step 1 - Execute Step 2 - Log title: C, alert: notice, desc: "Ending" My goal is to insert ...

Using PHP to send asynchronous requests to the server can greatly enhance

I have almost completed my project, but I am facing an issue with reading the data sent to the server. function main() { jQ(document).on("keyup", "form input", function () { var data = new FormData(); var value = jQ(this).val(); da ...