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

Passing an array from JavaScript to PHP and then storing it as a .json file

Query I am trying to pass an array to PHP and save it in a data.json file. However, the data.json file is being created but showing Null as output. I have spent about 2 hours on this code, checked numerous solutions on SO, but nothing seems to work. As I ...

The jQuery toggle functionality seems to be malfunctioning

I have created a form that should toggle (hide and show) with the click of a button, but for some reason it's not working. Can someone please take a look at my code below and let me know what I'm doing wrong? $(document).ready(function () { ...

Encountering a bindings issue when trying to utilize libxml-xsd within an electron application

Seeking guidance on validating an XML file against its schema within an electron application. Prior to adding the 'libxml-xsd' require statement to my angular2 service, it functioned properly. However, upon inclusion of this statement: const xs ...

What is the best way to have a button activate a file input when onChange in a React application?

Having an input field of file type that doesn't allow changing the value attribute and looks unattractive, I replaced it with a button. Now, I need the button to trigger the input file upon clicking. How can this be achieved in React? Edit: The butto ...

What is the best technique for creating a preloader that can seamlessly fill the background of a vector image?

I am looking for guidance on creating a CSS3 preloader using a vector image. My goal is to have the logo start off transparent with only the border visible, and as the loading occurs, fill in from bottom to top with the background color. Thank you to ever ...

Executing functions in beforeRouteEnter NProgress

When I attempt to call an API before navigating to a route, I encounter some issues. If I make the axios call inside beforeRouteEnter, everything works as expected: { beforeRouteEnter(routeTo, routeFrom, next) { NProgress.start() axios.get(' ...

Getting the Right Value: A Step-by-Step Guide to Setting the Default or Selected Value in

When creating directive form controls (text, select, radio), I am passing a value to the directive function. If this value is not set or empty, then the default value should be taken from the question data._pageAttributes.defaultValue. HTML <div ng-re ...

Sending values from multiple radio groups in JavaScript can be done by accessing each group individually and extracting

This is an add to cart system. Currently, I am able to send quantity with an ID. However, I also want to send radio group values. How can I achieve this? Here are my codes: product.php <script> jQuery(function ($) { $('.popbutton').on(&a ...

Tips for retrieving the text enclosed within a <span> tag using jQuery

I am new to jQuery and came across this code online for a questionnaire. I want to save the selected options but I am not sure how to do it. " $.fn.jRadio = function (settings)" What is the purpose of this setting? " var options = $.extend(_de ...

Transferring data between Javascript and PHP with AJAX and JQuery

I'm currently working on a basic web page that involves sending data from an HTML page to a PHP script and receiving some data back. My approach involves using AJAX, but for some reason, the PHP script doesn't seem to execute at all. Here's ...

Is there a quicker alternative to jQuery's .load() method?

My JSP index page features a navigation header and notifications panel, with other JSP pages being loaded into a specified div using JQuery.load(). This method was utilized to prevent the duplication of navigation and notifications across all pages. Wou ...

Incapable of composing text using the MUI SearchBar

I'm having trouble with my Material UI search bar - it's not letting me type anything into it. How can I resolve this issue? Despite trying the suggested code snippets from other answers, I keep encountering errors when integrating them into my ...

Utilizing jQuery UI Slider for Calculating Percentage

I recently worked on an example where I incorporated 5 sliders, which you can see here: Example: http://jsfiddle.net/redsunsoft/caPAb/2/ My Example: http://jsfiddle.net/9azJG/ var sliders = $("#sliders .slider"); var availableTotal = 100; ...

angular5: The ngFor directive will only function properly after the second button click

Here is my current situation: 1) When the user inputs a keyword in a text field and clicks on the search icon, it triggers an HTTP request to retrieve the data. 2) The retrieved data is then rendered in HTML using ngFor. The issue I am facing is that up ...

Javascript recursive method for fetching data entries

Seeking a solution to retrieve interconnected records based on a parent column, where the relation can be one or many on both ends. After attempting a recursive function without success, I found my code became overly complex and ineffective. Is there a st ...

Transform JavaScript variables into CSS variables

Similar Post: Avoiding repeated constants in CSS I am currently working on a javascript file that aims to adjust my site's resolution based on the width and height of the viewport. While I have successfully retrieved these values using JavaScript ...

Node.js: Module not found error

When I run the command below to install a module from the NPM registry: npm install dc All files are successfully installed, but upon running the script dc, it fails to resolve a dependency. $ node web-test.js module.js:340 throw err; ^ Error: ...

Update the content within every <td> element using AJAX/JQUERY on a table created from JSP

I have a database filled with descriptions and corresponding ID numbers. The table displays them like this: index.jsp <table> <tr> <td>Name:</td> <td>Id:</td> </tr> <c:forEach items ...

Using jQuery's AJAX function to redirect upon successful completion to a specific URL stored

After making an ajax call successfully, I want the current page the user is on to refresh. However, despite trying multiple approaches, nothing seems to be working. There are no errors or network activity showing in the Chrome debug. get[1] = "module=tick ...

Unable to establish a websocket connection with either Amber or NPM, uncertain of the reason

Amber CLI (amberframework.org) - v0.11.3 Crystal 0.27.0 [c9d1eef8f] (2018-11-01) LLVM: 4.0.0 Default target: x86_64-unknown-linux-gnu npm 3.5.2 Attempting to incorporate sockets using Crystal Lang and Amber has hit a snag. Despite following the guidelines ...