Updating an array in Vue.js without the need to reload all the data

Recently delving into Vue.js and JavaScript, I'm seeking guidance on updating an array (on Add/Edit/Delete) without having to reload all the data. The goal is to load all data only when initially opening the page with Addresses.

Take a look at my code:

<template v-else>
<div>
    <div class="page-header with-actions">
        <h1>Addresses</h1>
        <div class="actions">
            <b-btn @click="addAddress" variant="primary"><i class="oi oi-plus"></i> Add Address</b-btn>
        </div>
    </div>
    <div v-if="isLoaded === true">
        <div v-if="addressList.length">
            <b-form @submit.prevent="submit">
                <validation-summary :errors="errors"></validation-summary>

                <div class="row">
                    <div class="col-sm-4" v-for="address in addressList">
                        <div class="card bg-light mb-4">
                            <div class="card-header">
                                {{address.countryName}}
                                <div class="float-right">
                                    <b-btn @click="editAddress(address.id)" class="btn btn-default btn-sm" data-toggle="tooltip" title="Edit address">
                                        <i class="fa fa-edit" aria-hidden="true"></i>
                                    </b-btn>
                                    <b-btn @click="deleteAddress(address.id)" class="btn btn-default btn-sm" data-toggle="tooltip" title="Delete address">
                                        <i class="fa fa-trash" aria-hidden="true"></i>
                                    </b-btn>
                                </div>
                            </div>
                            <div class="card-body">
                                <em class="card-text">{{address.city}},</em><br />
                                <em class="card-text">{{address.streetAddress}},</em><br />
                                <em class="card-text">{{address.zip}}</em><br />
                            </div>
                        </div>
                    </div>
                </div>
            </b-form>
        </div>
        <div v-else class="alert alert-info" role="alert">
            There are no <strong>addresses</strong> yet!
        </div>
    </div>
    <add-address-modal ref="addAddressModal" @success="addressAdded"></add-address-modal>
    <edit-address-modal ref="editAddressModal" @success="addressEdited></edit-address-modal>
</div>
</template>

<script>
import Vue from 'vue';
import modalFormMixin from 'mixins/modal-form-mixin';
import formMixin from 'mixins/form-mixin';
import accountService from 'services/account-service';

import AddAddressModal from './add-address-modal';
import EditAddressModal from './edit-address-modal';

export default {
    mixins: [modalFormMixin],
    mixins: [formMixin],

    components: {
        'add-address-modal': AddAddressModal,
        'edit-address-modal': EditAddressModal
    },

    data() {
        return {
            addressList: [],
            isLoaded: false,
        }
    },

    async beforeRouteEnter(to, from, next) {
        next(async (c) => await c.initData());
    },

    methods: {
        async initData() {
            await this.loadAddressList(); //initial loading of addresses

            this.isLoaded = true;
        },

        async loadAddressList() {
            this.addressList = await accountService.getAddressList();
        },

        addAddress(data) {
            this.$refs.addAddressModal.show();
        },

        editAddress(id) {
            this.$refs.editAddressModal.show(id);
        },

        async deleteAddress(id) {
            await accountService.deleteAddress(id);

            this.updateAddressList(); 

            this.$root.successToast('Address deleted');
        },

        addressAdded() {
            this.updateAddressList();

            this.$root.successToast('Address added');
        },

        addressEdited() {
            this.updateAddressList();

            this.$root.successToast('Address edited');
        },

        updateAddressList() {
            // Update address list here without reloading all data
            // Consider using more efficient ways to manage the array
        }
    }
}
</script>

As we seek to enhance efficiency, it's essential to revise the loadAddressList() function to prevent redundant data reloading subsequent to Add/Edit/Delete operations. What approach do you recommend for accomplishing this effectively?

Answer №1

I have encountered this issue in the past, and it relates to Reactivity where changes may be delayed by a tick.

Here's a possible solution for your problem:

methods: {
  async loadAddressList() {
    this.addressList = await accountService.getAddressList();
    await this.$nextTick(); // waits for the next event tick before completing function.
  },
}

Check out Async update Queue for more information.

Additionally, explore Array Change Detection, which efficiently handles replacing arrays to reuse DOM elements.

Good luck with resolving the issue!

Answer №2

Is there a way to utilize the then function in your code? Perhaps in your initData method, you could consider implementing it like this?

async initData() {
    this.loadAddressList()
        .then(() => {
             this.isLoaded = true;
        });
    },

This approach eliminates the need to modify the loadAddressList method and avoids adding unnecessary functionality that it shouldn't handle.

UPDATE: Don't forget to ensure that your loadAddressList method actually returns a value, as using the async keyword implies returning a promise.

async loadAddressList() {
    this.addressList = await accountService.getAddressList();
    return true
},

By doing this, the use of .then() will be effective in your initData() method.

Check out the screenshot from https://javascript.info/async-await for more information.

https://i.sstatic.net/VS2Y1.png

Answer №3

When using vue 2.0, the most reliable way to ensure that data changes trigger a DOM update every time is by utilizing Vue.set with associative arrays (objects of objects). For optimal efficiency, your update or create request should return the object, allowing you to push it into the array or use the following method:

import Vue from 'vue'
createAddress(data) {
   axios.POST('your-url', data).then(address => {
       Vue.set($store.addresses, address.id, address)
   })
}

In order to implement this, you will need to adjust your array of addresses to be associative like so:

import Vue from 'vue'

getAddresses(state) {
   axios.GET('your-url').then(addresses => {
       addresses.forEach(address => {
            Vue.set(state.addresses, address.id, address)
       })
   })
}

This can also be achieved using:

Object.assign(state.addresses[address.id], address)

However, based on personal experience, this approach may sometimes fail to update the DOM for reasons unknown.

Your address_list should then be computed to point to the addresses within your state management system (such as Vuex):

computed: {
    address_list() {
        return $store.addresses
    }
}

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 NodeJS and ExpressJS: Unveiling the significance of routes/index.js

Can you explain the function of this particular file? Does this file handle all the GET and POST requests in a project? If so, wouldn't it become excessively long and complex for larger projects? I encountered an issue when trying to call a POST re ...

Utilizing a Grunt task to inject code into an AngularJS file

Hey there! I'm currently looking for a way to add some code into my app.js file that will only execute when I run the "grunt serve" task. This code is just two lines of javascript that should be present when I test the app on my local environment. Unf ...

Is there a way to send a promise resolve or reject from a function code within router.post() in Express?

Below is my code in express (node.js) router.post('/example.json', function (req, res) { // getFileInfo is a function to return an array return getFileInfo(req.body.fileList).then((array) => { axios({ method: 'post', ...

What is the best way to organize a column in a table to prevent the display of duplicate values in React?

As I work on managing teams for an alumni group's webpage, I have a table with fields such as year, team category (Football, etc), and members (many-to-many relationship). My goal is to display a list of categories on the main page, with each category ...

Design an interactive div element that allows users to modify its content, by placing a span

Here is an example of the desired effect: ICON LINE - 1 This is some sample text inside a div element and the next line should begin here ICON LINE - 2 This is some sample text inside a div element a ...

Numerous linkages facilitated by node-mongodb-native

Currently, I am working on a function aimed at inserting a document into a MongoDb database using the node-mongodb-native module. The function works perfectly fine, except when multiple documents are inserted back-to-back. To test how my function handles m ...

Craft a FormType showcase using the dynamic duo of Ajax and Jquery

If you'd like to check out the code snippet for reference, please visit: This view serves as the canvas where innovation blends with execution. As I embark on this journey towards dynamic form creation, every step counts. Thank you for being part of ...

Challenges with variable scopes and passing variables in Ionic 2 (Typescript)

In my Ionic 2 TypeScript file, I am facing an issue with setting the value of a variable from another method. When I close the modal, I get undefined as the value. I'm encountering difficulty in setting the value for coord. export class RegisterMapP ...

jQuery is used to make an object fade out once another object has been moved into place

As I delve into the world of jQuery, I've decided to create a simple Super Mario imitation. The concept is to control Mario using arrow keys and fade out mushrooms once Mario reaches them. However, my attempts at achieving this result have not been su ...

Utilize Typescript/Javascript to utilize the Gmail API for sending emails via email

I am trying to send emails from my application using my Gmail account with Ionic. I have followed tutorials from SitePoint and Google Developers. Here is how I'm initializing the client: client_id: gapiKeys.client_id, discoveryDocs: ["https://www.goo ...

Utilizing Ajax for Dynamically Filling a Dropdown Menu

My journey into the world of Ajax has led me to a state of confusion and frustration. The task at hand is to populate the first box with customer data from the database, then use the customerID to retrieve all vehicleID's using the select.php script. ...

The outcome of the JQuery function did not meet the anticipated result

Here is the code I am using: $("p").css("background-color", "yellow"); alert( $("p").css("background-color")); The alert is showing undefined instead of the expected color value. I have tested this code on both Google Chrome and Firefox. Strangely, it w ...

Incorporating an offset with the I18nPluralPipe

Having trouble with my multiselect dropdown and the text pluralization. I attempted to use the I18nPluralPipe, but can't seem to set an offset of 1. ListItem = [Lion, Tiger, Cat, Fox] Select 1 Item(Tiger) = "Tiger", Select 3 Item(Tiger, Cat, Fox) = ...

Tips for navigating to the top of the browser window from the middle or bottom using JavaScript in Protractor

I am in need of clicking the element positioned at the bottom of the page first and then I must click on an element located at the top of the page. In other words, scroll up where it is not visible to the browser. To scroll down, I have used: browse ...

Resolving the Issue with onClick Events in Closures

Secrets of the JavaScript Ninja provides an interesting example: HTML <button id="test">Click me!</button> JavaScript var button = { clicked: false, click: function() { this.clicked = true; console.log("this:", this, ...

Leverage a function in an external JavaScript file within Angular 4

I am facing an issue while attempting to integrate a JavaScript file into my angular component. I have successfully loaded the full minified version from this source: https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image.all.min.js and ...

What is the best way to create a clickable <li> element from AJAX search results that display dynamic HTML?

Utilizing AJAX technology, I have implemented a live search feature that populates results from a database as the user types in a text field. The results are presented in an unordered list format. My goal is to allow users to click on an item within the li ...

Error: Vue.js is unable to find the reference for "_vm.KisanData" and throws a TypeError

I need assistance in fixing an error that I am encountering. The issue arises in this method where I am using KisanData, but I am unable to resolve it. const API_URL = "http://localhost:3000/User"; export default { name: "home", info(){ ...

Is it possible to change the return value of an Object key to something other than a string in REACT? Issue with RE

In an attempt to modify the data in an object using the setState method in 'react', I decided to take a different approach. Instead of creating a function for each key in the state object, I attempted to create one object and return the key from ...

What is the best way to iterate through only the selected checkboxes to calculate their

I am in need of calculating the selected checkboxes only within a table field (harga_obat*jumlah) Below is my foreach data: @foreach ($obat as $o) <tr> <td> <input id="check" type="checkbox" name="select[]" value="{{ $o->nam ...