VueJS Component has trouble refreshing the DOM content following an AJAX Promise

I've encountered issues updating data in my Vue application after an AJAX callback. I have previously resolved similar problems by using Vue.set, but for some reason, it's not working for me today.

The only difference is that I am calling a service within a component (.vue file).

When I inspect the DOM with VueJS tools in Chrome, I can see the data from the service being assigned to my module.options property in the created function, but it's not rendering on screen.

Below is the full .vue component and a screenshot showing the data logged in the dev tools and the template not rendering it.

The snippet provided won't run, but it's a nicer format than pasting it directly into the post.

To summarize, the response from

this.build_service.getOptionsForModule
is as expected and
Vue.set( this.module, 'options', res.options )
appears to work, but it doesn't update the DOM.

Any thoughts on why this might be happening?

<template>
<div class="panel">
        <div class="panel-heading">
            <h2 class="panel-title">
                <a data-toggle="collapse" :href="'#collapse' + module.field" :data-parent="'#' + group_name" >
                    {{module.title}}
                    [{{module.options.length}}]
                </a>
            </h2>
        </div>
        <div :id="'collapse' + module.field" class="panel-collapse collapse">
            <div class="panel-body">
                <div class="form-group">
                    {{module}}
                    
                    <select id="" data-target="#" class="form-control" :disabled="!module.is_active">
                        <option :value="{}">Select {{module.title}}...</option>
                        <option v-for="option in module.options" :value="option" v-html="option.name">
                        </option>
                    </select>
                </div>
                <div class="form-group">
                    <button class="btn btn-success mediumButton" @click="create( module )">
                        Create
                    </button>
                    <button class="btn btn-primary mediumButton" @click="edit( module )">
                        Edit
                    </button>
                </div>
            </div>
        </div>
    </div>
</div>
</template>

<script>

    import { EventBus } from '../event-bus.js';
    var BuildService = require('../services/build-service');

    export default {
        name: 'module',
        props: [ 'group_name', 'module' ],
        data: function() {
            return {
            
            }
        },
        created: function() {
            console.log('single module component created');

            this.build_service = new BuildService();

            console.log( this.module );

            // if there are no options, load from service
            if( !this.module.options.length && this.module.parent === '' ) {

                this.build_service.getOptionsForModule( this.module )
                    .then(( res ) => {

                        if( res.length ) {
                            res = res[ 0 ];

                            Vue.delete( 
                                this.module,
                                'options'
                            );

                            Vue.set( 
                                this.module,
                                'options', 
                                res.options
                            );

                        } else {
                            console.error('no options found');
                            // TODO: status alert
                        }
                    })
                    .catch(function(err){
                        console.error(err);
                    });
            }
        },
        methods: {
            create: function( module ) {
                console.log('creating record for', module);
            },
            edit: function( module ) {
                console.log('editing', module);
            }
        }
    }

</script>

Answer №1

It's a common occurrence for me to find solutions to my own questions shortly after posting them, which may benefit others in the future.

In this particular instance, I encountered an issue with modifying a prop passed down from a parent component, as it cannot be directly altered from the child component without sending events upwards to facilitate data flow.

To address this, I needed to create a copy of the prop within the data structure (as pointed out by a helpful commenter who highlighted that I had not registered the module in the data structure).

After consulting the documentation, I discovered a straightforward solution (RTFM!!)

One-Way Data Flow

All props establish a one-way-down binding between the child property and the parent property

...

In cases where there is temptation to mutate a prop, two scenarios typically arise: 1. The prop is utilized solely for passing an initial value, but the child component desires to use it as a local data property thereafter;

...

The recommended approach for handling these scenarios is:

Define a local data property that initializes using the prop’s initial value:

props: ['initialCounter'],
data: function () {
    return { counter: this.initialCounter }
}

https://v2.vuejs.org/v2/guide/components.html#One-Way-Data-Flow

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

Is there a more secure alternative to using the risky eval() function? Do I need to take the lengthier route by implementing a switch case instead?

I've been practicing and honing my Javascript skills by working on a calculator code that initially had lots of repetitive lines. I managed to simplify it, but I am aware that using the eval() method is not generally recommended. let current = 0; f ...

Issue with interaction between jQuery AJAX and PHP login functionality

Currently, I am attempting to implement an inline login feature that triggers whenever the PHP $_SESSION['logged_in'] variable is not defined (this variable gets set when a user logs in). The challenge arises when I try to keep the user on the sa ...

I am currently working on determining whether a given string is a palindrome or not

I'm currently working on a function that checks whether a given string is a palindrome. So far, my tests are passing except for the following cases: (_eye, almostomla, My age is 0, 0 si ega ym.) This is the function I've implemented: function pa ...

Trouble Arising from the Lack of Coordination Between CSS Transition and JavaScript Update Triggered by Element

I'm currently working on a web development project that involves a list of clickable elements. When one of these elements is clicked, it should become active and trigger a CSS transition (such as a transform) with a duration of 200ms. Additionally, I ...

How can I obtain the coordinates when the mouse enters Vue?

Trying to create an animation triggered by the mouseenter event in Vue, I ran into a roadblock - obtaining the coordinates of the sections. <script setup> function fetchCoordinates(e) { const coords = { x: e.clientX, y: e.clientY } // This seems to ...

What is the best way to restrict navigation for a subroute in Vue.js?

One of the great things about beforeRouteLeave is its ability to prevent navigation under specific conditions. In my setup, I utilize a subroute to display a part of the page. I am looking for a way to implement a navigation guard on the subroute to prohi ...

How to Call a Nested Object in JavaScript Dynamically?

var myObj = { bar_foo : "test", bar : { foo : "hi there"; }, foo : { bar : { foo: "and here we go!" } } } How can we achieve the following: var arr = [["bar", "foo"], ...

Executing a JavaScript function when an element is clicked using inline

Is it possible to write the code below in a single line? <a href="#" onClick="function(){ //do something; return false;};return false;"></a> As an alternative to: <a href="#" onClick="doSomething(); return false;"></a> functio ...

Executing a function when a user chooses to exit a webpage using the @HostListener('window:beforeunload') method

Utilizing @HostListener('window:beforeunload') allows me to detect when a user navigates away from the page, prompting a dialog window to open. I wish for an event to be triggered or a method to be executed if the user chooses to leave the page. ...

Utilize Ajax to automatically populate a textbox with suggestions

I'm retrieving data via an AJAX call. How can I bind the data for auto-completion in a text box using both the name and ID as fields? What is the best way to bind this data in the frontend and retrieve the selected name's ID in the backend using ...

Tips for integrating JavaScript libraries with TypeScript

I'm looking to add the 'react-keydown' module to my project, but I'm having trouble finding typings for it. Can someone guide me on how to integrate this module into my TypeScript project? ...

Manipulating binary data through the use of encodeURIComponent

Currently, I am reading a binary file by making a jQuery ajax get request. The file (a zip file in this instance) is returned as a string. After performing some actions on the file within the browser without modifying it, I need to send it back to a server ...

Using a JavaScript variable in conjunction with an AJAX-PHP variable

When using an ajax call to refresh an external php file "commentS.php" every 3 seconds, I encountered a problem. Despite expecting the variable in the hidden input field (name="idd") to be reflected on the "commentS.php", it did not happen as anticipated. ...

Having issues with closing a div tag using $.after() function

This issue can be better understood with an example: http://jsbin.com/lavonexuse The challenge here is to insert a full-width row after a specific column (identified by the class .insertion-point) when "Insert Row" is clicked. The problem I'm facing ...

Extracting information from a string with JSON in Javascript

Can you assist me? I have developed a web service that provides a clean string after clicking on the URL: { "PersonID": 125, "Title": "Security Officer", "Company": "TSA", "CellNum": "423-915-3224", "EmergencyPhone": "", "Email": " ...

Is it possible to dispatch actions from getters in Vuex?

Fiddle : here Currently, I am in the process of developing a web application using Vue 2 with Vuex. Within my store, I aim to retrieve state data from a getter. My intention is for the getter to trigger a dispatch and fetch the data if it discovers that t ...

What is the best way to pass and retrieve parameters in a Spring application?

I am attempting to perform a simple task using AJAX, sending a request with either a GET or POST method. The goal is to send 2 parameters in JSON format and receive them back in a response. However, I keep encountering a 400 error and other unknown errors ...

Sending returned values from a promise to the calling function in Angular

I have a created a promise to retrieve values from a service and then assign them to variables trans and confidence, which should be used as transcript and conf in the save_data function. How can I return these values to the calling function and ensure tha ...

The Vue $refs Object is classified as 'unidentified' in nature

I'm encountering an issue while attempting to utilize $refs in my Vue 3 application. Each time I try, I receive the Typescript error stating that "Object is of type 'unknown'". I am uncertain about how to resolve this problem. Here's ...

Toggle the backgroundImage visibility by setting it to either hidden or displayed using jquery

$('.arrow').css("background-image", "url('../img/arrow.png')").hide(); I have implemented a custom solution using CSS and jQuery to hide the downward arrow when scrolling down on my webpage. `$( document ).ready(function() {
 co ...