Names changes and deletion of files that have been uploaded- Using Vue.js

I attempted to use v-model in order to rename files before uploading them to the system, but unfortunately, it was not successful. As a result, I developed an alternative solution which is functioning perfectly, except for the fact that I am unable to retain the text value inputted. The preventdefault method does not seem to work as expected.

In this scenario, I uploaded 3 images and renamed them as First, Second, and Third.

<div>
    <input type="file" @change="addFile" multiple>Choose file
</div>

<div v-if="selectedFiles && selectedFiles.length>0">
       <div v-for="(item, index) in selectedFiles">
            <span>{{ item.name }}</span>
            <input type="text" v-model="" placeholder="Rename File" @change="renameFile(item,event)"/>
            <button @click="removeFile(event,item,index)"></button>                                    
        </div>
 </div>   
 <button @click="uploadDrawings">Upload Files</button>                                        
data: {
      selectedFiles: [],
      renameFiles: [],
      finalFiles: [], 
},
methods: {

    addFile(event) {
        _.each(Array.from(event.target.files), function (file) {

            var existed = _.find(app.selectedFiles, function (item) {
                return item.name == file.name;
            });

            if (!existed) {
                app.selectedFiles.push(file);
            }
        });
    },
    renameFile(item, event) {
        if (app.renameFiles.filter(x => x.oldName == item.name).length > 0) {
            var objIndex = app.renameFiles.findIndex(x => x.oldName == item.name);
            app.renameFiles[objIndex].newName = event.target.value;
        }
        else {
            app.renameFiles.push({
                oldName: item.name,
                newName: event.target.value
            })
        }
    },
    removeFile(e,item, index) {
        e.preventDefault(); // while removing an item, the text value changes.
        app.selectedFiles.splice(index, 1);
        var objIndex = app.renameFiles.findIndex(x => x.oldName == item.name);
        app.renameFiles.splice(objIndex, 1);
    },

    uploadDrawings() {
       app.isLoading = true;
       if (app.selectedFiles.length == 0) {
         return;
     }

     _.each(app.selectedFiles, function (item) {
          var blob = item.slice(0, item.size, 'image/jpg');
          var name = app.renameFiles.filter(x => x.oldName == item.name);
          app.finalFiles.push(new File([blob], name[0].newName + '.jpeg', { type: 'image/jpg' }));
});
}

Upon removing an item from top to bottom, the text box does not maintain its value. For example, 'First' was assigned for '091646'.

Despite this issue with the text boxes, the files are correctly named in the finalFiles. It is only the text box that presents a challenge.

I would greatly appreciate any assistance in resolving this matter and retaining the textbox values. Thank you in advance.

Answer №1

Issue with Key Attributes

The elements in the v-for loop are not correctly keyed in your code, causing Vue to assign keys based on their index. This can lead to problems when items are added or removed from the middle of the list.

Resolution

To solve this issue, make sure to include a unique key attribute for each item in the v-for loop using a combination of an index and a unique identifier like filename:

<div v-for="(item, index) in selectedFiles" :key="index + item.name">

Missing Two-Way Data Binding

When items are removed from the list, textboxes lose their values due to the absence of two-way data binding (v-model).

Fix

Adjust renameFiles[] to store only strings corresponding to files in selectedFiles[] at the same index. Update methods accordingly to simplify the code:

export default {
  ⋮
  methods: {
    addFile(event) {
      this.selectedFiles = Array.from(event.target.files)
    },
    removeFile(e, item, index) {
      this.selectedFiles.splice(index, 1)
      this.renameFiles.splice(index, 1)
    },
    ⋮
  },
}

This change also allows you to use renameFiles[] as v-model for the rename input fields:

<input type="text" v-model="renameFiles[index]" placeholder="Rename File" />

See demo

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

Testing an API request using Jasmine for unit testing

I am currently working on writing unit tests for the website I'm developing at my job. One thing I'm struggling with is how to effectively test an API call within one of my Vue components. Let's say I have the following code snippet in my V ...

Is it possible to overlay color on top of a div background? (i.e. modify div color without altering the 'background-color' property)

Can you apply a color "on top of" a div's background? I'm looking to change the displayed color of a div without altering the 'background-color' value. I need to keep the background-color for comparison when divs are clicked: var pick ...

moving a simulated element to a new location

Looking for some help with my html/CSS code that creates a unique element at the bottom of a div with an image background. The shape I've created is positioned at the bottom of the div... Below is the HTML: <div style="background-image:url(&apos ...

Exploring JSON data hierarchies with AngularJS using ng-options

In my web app, I am utilizing AngularJS to create two dropdown lists using ng-options. The first dropdown displays a list of countries The second dropdown provides language preferences for the selected country As I am still new to AngularJS, I am able t ...

What is the best way to convert template interpolation using different words into a correct expression syntax in JavaScript regex?

I have a string that contains template interpolation along with words that are not inside the interpolation. The string can be in one of these various forms: foo{{bar}} {{foo}}bar foo{{bar}}baz {{foo}}{{bar}} foo {{foo}} {{foo}}bar{{baz}} The text interpo ...

What is the best approach for writing an asynchronous function while utilizing $rootScope.broadcast within a continuous loop?

At least 10 times a second, I have a function that is called. Each time, there are approximately 100 records with variations in LastSeenTime and ReadCount. In this simulation scenario, I understand the behavior; however, in real-time, the number of records ...

Encrypting sensitive information in JavaScript and Angular 2: SecureString

Is there a way to securely copy sensitive data to the clipboard in javascript/Angular2, ensuring that the string remains confidential by removing it from computer memory when no longer needed? In Microsoft .Net, there is a feature called System.Security.S ...

Is there a way to verify the results of a Python script within a PHP webpage?

For my school project, I am creating a PHP website where I want to implement a Python code Quiz. I envision a scenario where users can input Python code in an on-page editor/IDE and the output is checked automatically using PHP If-function to determine cor ...

Developing a pop-up feature that triggers upon clicking for a miniature rich text editing

Looking to integrate the Tiny rich text editor into my code. Check out the TextEditor.js component below: import React from 'react'; import { Editor } from '@tinymce/tinymce-react'; class App extends React.Component { handleEditorCha ...

Include a single element repeatedly on a single webpage

Is there a way to add the same component multiple times on one page? I have an input component that receives props and performs certain functions. I need to include more than one instance of this input component on a single page, but when I try to copy and ...

There seems to be an issue with the server: Xt1.deprecate function is not defined

Currently, I am utilizing next.js version 13.4.12 with next-auth version 4.22.3 and prisma version 5.0.0, while also incorporating @next-auth/prisma-adapter version 1.0.7 in a TypeScript setup. Additionally, I have diligently followed all the necessary bo ...

Limit the frequency of rendering JSX elements in React by implementing debouncing techniques

Is there a way to delay the rendering of a jsx element in order to smooth out the animation? I have an expanding panel with content inside, and when the panel is empty, the animation works well. However, if the panel already contains content, the expansion ...

Change the text field's border color if the field is not empty

On my website, there is a TextField where users can enter values to perform a site search. My question pertains to the border color of this field. Normally, the border color is black when the field is not in use. However, when a user clicks on the field an ...

Using a custom filter in AngularJS allows for seamless data filtering directly from the initial dataset

My goal is to implement a custom filter that will allow me to filter data based on a search word. The scope attribute gets populated in the controller's scope as shown below: naApp.controller('naCareNewTicketCtrl', ['$scope', &apo ...

Insects featuring a button and tooltip duo creating a captivating "pull-effect"

Why is the button pulling when I move the cursor over a camera? Is there a way to solve this issue? <div class="input-group-btn advanced-group"> <button class="btn btn-default" data-toggle="tooltip" data-placement="bottom" title="Send Imag ...

Is onMouseLeave failing to trigger upon exiting an element?

Having an issue with the onMouseLeave event in React. It seems to be triggering when hovering over other elements like the navbar or console, but not when leaving the intended element. function GameCard({name, about, image}) { const [active, ...

Comparing the architecture of two JSON objects in JavaScript without taking into account their actual content

One of the tools I rely on for my projects is a Node.js based mock server that helps me specify and mock API responses from the backend. However, it would be beneficial to have a way to ensure both the backend and frontend are in sync with the specified st ...

Synchronizing Vuetify Carousel with dynamic route parameters

I'm facing an issue where the v-carousel value does not sync correctly with a route parameter using a computed property. Despite waiting for the mounted hook, the carousel seems to emit its own input and disregard the initial value from the route para ...

Discovering the value of an object through its prototypes

Is it possible to create a function that can locate the value "5" within an object's prototype? What is the proper algorithm to achieve this? var rex = { "Name": "rex", "Age": 16, } te = { "to": 5, } rex.te = Object.create(te); function findValu ...

unable to render axios retrieved data in vuejs v-for loop

After checking VueDev tools, it appears that the axios get request is returning a data array. However, despite my efforts, I am unable to display this data. (I'm clearly new at this!) Any ideas on what step I may be missing? <template> < ...