What is the best way to pass an array of objects to a component as a prop and then distribute individual objects within the array as props to nested components?

Below this post, I delve into my desired goals and what has almost worked in my endeavors

In my application, I have both the <oo-upload> and <oo-uploads> components defined. Essentially, <oo-uploads> showcases a table of <oo-upload> components to create a file uploading plugin for my app. The variable uploads holds a list of all uploads, with each individual upload being defined by upload.

<body>

    <script type="x/template" id="oo-upload-template">
        <td>@{{ upload.file.name }}</td>
        <td>@{{ upload.file.size }}</td>
        <td>
            <div class="ui indicating progress floated" v-progress="upload.progress">
                <div class="bar"><div class="progress"></div></div>
            </div>
        </td>
        <td>
            <button class="ui primary button" v-on:click="upload" v-if="status < 1">Upload</button>
            <button class="ui red button" v-on:click="destroy" v-if="status == 2">Delete</button>
        </td>
    </script>

    <script type="x/template" id="oo-uploads-template">
        <table class="ui very basic table">
            <thead>
                <tr>
                    <th class="two wide">Filename</th>
                    <th class="two wide">Filesize</th>
                    <th class="ten wide">Status</th>
                    <th class="two wide">Actions</th>
                </tr>
            </thead>

            <tbody>
                <tr v-show="uploads.length==0">
                    <td colspan="4" class="ui center aligned">No files added!</td>
                </tr>
                <tr v-for="upload in uploads">
                    <oo-upload :upload="upload"></oo-upload>
                </tr>
            </tbody>

            <tfoot class="full-width">
                <tr>
                    <th colspan="4">
                        <div class="ui right floated small green labeled icon button" v-on:click="uploadDialog">
                            <i class="plus icon"></i> Upload File
                            <input type="file" style="display:none;" v-el:uploader v-on:change="addFiles" multiple>
                        </div>
                    </th>
                </tr>
            </tfoot>
        </table>
    </script>

    <div id="app">
        <div class="ui container">
            <oo-uploads :uploads="uploads"></oo-uploads>
        </div>
    </div>
    <script type="text/javascript" src="js/app.js"></script>
</body>

The current issue is that an objUpload object is not correctly passed to each instance of the <oo-upload> component. Rather than an object, the Vue debugger indicates that a function is being passed to the component. However, <oo-uploads> does not encounter any problems when receiving uploads as a prop.

var Vue = require('vue'),
    VueRouter = require('vue-router'),
    VueResource = require('vue-resource'),
    Vuex = require('vuex'),
    VueValidator = require('vue-validator');

/*
PLUGINS
 */

Vue.use(VueResource);

/*
CUSTOM DIRECTIVES
 */

Vue.directive('progress', {
    bind: function () {
        $(this.el).progress();
    },
    update: function (value) {
        $(this.el).progress('set percent', value);
    }
});

/*
OBJECTS
 */

function objUpload (file) {
    this.progress = 0;
    this.file = file;
    this.status = 0;
}

/*
COMPONENTS
 */

Vue.component('oo-upload', {
    props: ['upload'],
    template: '#oo-upload-template',
    methods: {
        upload: function () {
            this.upload.status = 1;
            this.$http.post('/upload', this.upload.file, { progress: function (pe) {
                this.progress = Math.floor(pe.loaded/pe.total * 100);
            }}).then(function (result) {
                this.upload.status = 2;
            }, function (result) {
                this.upload.status = -1;
            })
        },
        destroy: function () {

        }
    }
});

Vue.component('oo-uploads', {
    props: ['uploads'],
    template: '#oo-uploads-template',
    methods: {
        uploadDialog: function () {
            $(this.$els.uploader).click();
        },
        addFiles: function () {
            var uploader = this.$els.uploader;
            for (var i = 0; i < uploader.files.length; i++) {
                var file = uploader.files[i];
                this.uploads.push(new objUpload(file));
            }
        }
    }
})

/*
CONSTANTS
 */

Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name="_token"]').attr('content');

/*
INSTANCE
 */

var vm = new Vue({
    el: '#app',
    data: {
        uploads: [],
    },
});

EDIT: When I directly pass the uploads array to a single instance of <oo-upload> within <oo-uploads>, it successfully passes down the entire array without issues. However, the problem arises when attempting to iterate through the array and pass only the objUpload objects.

EDIT2: My main goal is to limit the data scope being passed down to only what is essential for each component. I aim for the upload component to focus solely on the assigned upload. While I understand that there may be flaws in my approach or limitations to my implementation, I seek guidance on achieving a similar outcome.

Answer №1

As per the guidelines provided in the Vue.js documentation, it is suggested to always include a single root-level, plain element in templates.

Hence, it is advisable to wrap the oo-upload-template with a tr tag and make the following adjustment:

<tr v-for="upload in uploads">
  <oo-upload :upload="upload"></oo-upload>
</tr>

This snippet should be replaced with:

<tr is="oo-upload" v-for="upload in uploads" :upload="upload"></tr>

To view an improved version, check out this updated fiddle.

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

Executing the callback function

I am facing a situation where I have a Modelmenu nested within the parent component. It is responsible for opening a modal window upon click. Additionally, there is a child component in the same parent component that also needs to trigger the opening of a ...

Synchronizing validation processes across both front-end and back-end applications

How do you ensure validations remain synchronized between front-end and back-end teams when working with laravel? While I found some information in this post, I am curious about how it specifically applies to laravel. I came across the laravel js validat ...

Tracking the number of form submissions on a PHP website

I am looking to add a counter feature to my website where every time a form is submitted, the count increases for all visitors. The starting number will be 0 and each form submission will increment the count. While I can manage the count using JS/jQuery w ...

How can we transfer parameters in JavaScript?

My vision may be a bit vague, but I'll try to explain it as best as I can. I want to implement multiple buttons that can toggle the visibility of a div (I have this functionality working already). Each button should carry two values (a number and a l ...

v-tooltip specifically designed for the append-icon

I'm currently working with Vuetify and facing an issue with applying a tooltip only for the append-icon in a v-text-field. The current problem is that the tooltip does not work for icons at all! View code on CodePen <v-tooltip bottom> < ...

Filtering Gridviews with Javascript or jQuery

My current project involves using an ASP.NET GridView with multiple ListBoxes representing Departments, Categories, Faculties, and more. The data in these ListBoxes and the GridView is dynamically loaded from a MSSQL database in the codebehind. I am in ne ...

Guide to filling a dropdown menu by aligning with the text it contains?

I've set up two dropdown select boxes below that are exactly the same: HTML <select id="ddl1" name="ddl1"> <option value="1">TEXT 1</option> <option value="2">TEXT 2</option> <option value="3">TEXT 3&l ...

Implementing Various Conditions in ng-if Using AngularJS

I have a scenario in my AngularJS application where I need to display different buttons based on the value of type. If type === 'await_otp', then I should display two buttons (resend OTP and cancel), if type === 'submitted', then only t ...

Is there a way to get a Chrome extension to run automatically in the background?

I am looking to develop a custom chrome extension with a countdown timer functionality that automatically runs in the background. However, I am facing an issue where my background.js file is unable to access the popup.html file. How can I execute scripts i ...

Can you explain the distinctions among 'data:', 'data: ()', and 'data()' when working with Vue.js?

While exploring the Vue.js documentation, I came across two ways to define data: data: {} and data() { return; }. data: { defaultLayout: 'default' } data() { return { defaultLayout: 'default' } } However, there is ...

Guide on how to utilize JavaScript to redirect to a URL for PUT or POST requests by clicking a button

I have a button <button class="delivery-orders-button" onclick="markDone(${order.order_id})">Dispatch order</button> and my goal is to have the markDone function redirect the user to a designated page, similar to how forms ...

Counting the number of PHP inputs in a field

Hello, I am using a PHP script from Steve Dawson's website. To display the output on my HTML page, I am utilizing this AJAX script: <script> $.ajax({ type:'GET', url:'http://www.solariserat.se/count.php', data: ...

Error thrown due to inability to map imported JSON data

Displayed below is a snippet of data stored in the data.json file: [ {"id": 23, "name": "Good!", "state": "OK"}, {"id": 24, "name": "Not good...", "state": " ...

When utilizing TinyMCE in numerous Vuetify dialogs, the editor appears completely empty

My challenge is using TinyMCE in multiple dialogs, as switching dialogs causes the TinyMCE editor to become blank and uneditable. To showcase the issue I'm facing, I have prepared a demo accessible here: https://codesandbox.io/s/tinymce-vue-demo-fork ...

Adjust the flexslider to transition to a new slide when hovering over the thumbnails

I have a flexslider with thumbnails like this ; https://i.stack.imgur.com/9bfC2.jpg I am looking to change the slide when the user hovers over the thumbnails. How can I achieve this functionality? Here is the jQuery code I am currently using to set up th ...

Troubles with Promise.all and json() in JavaScript causing errors being logged as "invalid function"

I'm experiencing some difficulties with the "Promise.all" method. Essentially, I have an array of URLs (here is a simple one if you want to test it: const urlArray = [ "https://coverartarchive.org/release/985adeec-a1fd-4e79-899d-10c54b6af299&qu ...

Create a simulated reload of the window location using sinon

Currently, I am working on creating tests using sinon for a specific section of Vue code that triggers a page reload with window.location.reload();. Even though the code functions properly, the test is encountering a failure with the error message Error: ...

How can you update the options within a select tag depending on the selected index of another select tag using AngularJS?

Consider the following code snippet: $scope.letters = ['A', 'B', 'C', 'D']; $scope.numbers = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]; $scope.selectedLetter = 0; There are two select tags in t ...

How to stop parent event propagation in jQuery

I am facing a frustrating issue with my code. Every time I toggle a checkbox, the parent element's click event also triggers. I have experimented with various solutions like: event.stopImmediatePropagation(); event.stopPropagation(); event.preventD ...

Unable to retrieve dropdown value using JavaScript and display it in a div

javaScript code: Retrieving data from a dropdown and displaying it in the inner HTML of a div. function showcost() { var days = document.getElementById("Ddays"); var Dudays = days.options[days.selectedIndex].text; var div = docu ...