Vue - Child component not refreshing its data and triggering a re-render

In this scenario, I have the ability to upload a single LiteratureReview which can contain multiple Quote components. Essentially, I am dealing with parent-child relationships between LiteratureReview and Quote. Data retrieval and submission are done using Axios and my backend is built on Laravel.

Both LiteratureReview and Quote components fetch their data from the app instance. When making a post request, updating and re-rendering for LiteratureReview works fine. However, when attempting to add a Quote to a literature review, it does not update automatically, requiring a page refresh.

app.js (or main.js)

export const app = new Vue({
    el: '#app',

    data: function () {
        return {
            literatureReviews: [],
            quotes: [],
        }
    },
    mounted() {
        axios.all([
            axios.get('/literature-review'),
            axios.get('/quote')
        ]).then(axios.spread((first_response, second_response) => {
            this.literatureReviews = first_response.data
            this.quotes = second_response.data
        }))
    }
});

index.blade.php

<literature-review v-for="(literatureReview, index) in literatureReviews" v-bind:loop="index + 1"
            v-bind:key="literatureReview.id" v-bind:literature_review_id="literatureReview.id"
            v-bind:topic="literatureReview.topic" v-bind:type="literatureReview.type"
            v-bind:year="literatureReview.year" v-bind:link="literatureReview.link"></literature-review>

LiteratureReview (Component; Parent)

<template>
    <div class="literature-card mb-5 rounded">
        .
        .
        .
        <quote v-for="quote in filterByLiteratureReview(quotes, literature_review_id)" v-bind:key="quote.id"
            v-bind:literature_review_id="literature_review_id" v-bind:quote="quote.quote" v-bind:page="quote.page"></quote>
    </div>
</template>

<script>
    import { app } from '../app.js'
    import { store } from '../app.js'

    export default {
        props: ['loop', 'literature_review_id', 'topic', 'type', 'year', 'link'],
        data() {
            return {
                quotes: app.quotes,
                sharedObject: store,
            }
        },
        methods: {
            filterByLiteratureReview(quotes, literature_review_id) {
                return this.quotes.filter(quote => quote.literature_review_id == literature_review_id)
            },
            updateLitIdForAddingQuote(value) {
                this.sharedObject.setLiteratureReviewIdAction(value)
            },
        }
    }
</script>

Quote (Component; Child)

<template>
    <div>
        <div class="row no-gutters px-3 pt-3">
            <div class="col" style="white-space: pre-wrap;">{{ quote }}</div>
        </div>
        <div class="row no-gutters" style="border-bottom: solid black 2px;">
            <div class="col py-4 pr-3 text-right">Pg {{ page }}</div>
        </div>
    </div>
</template>

<script>
    export default {
        props: ['id', 'literature_review_id', 'quote', 'page'],
    }
</script>

Axios posting a Literature Review

axios.post('/literature-review', {
    topic: this.topic,
    type: this.type,
    year: this.year,
    link: this.link,
}).then( response => {
    $('#addSourceModal').modal('hide')
}).finally(
    axios.get('/literature-review').then(response => app.literatureReviews = response.data)
)

Axios posting a Quote

axios.post('/quote', {
    literature_review_id: this.sharedObject.state.literature_review_id,
    quote: this.quote,
    page: this.page
}).then( response => {
    console.log(response)
    $('#addQuoteModal').modal('hide')
    // location.reload();
}).finally(
    axios.get('/quote').then(response => app.quotes = response.data)
)

Answer №1

After reading this insightful article, I found a solution that somewhat guided me through the process. Essentially, the data gets updated when the submit button on the popup modal is clicked. To achieve this, I created a button that triggers an event to the root component using

this.$root.$emit('forceRerender')
. This event is then received by the LiteratureReview component with
this.$root.$on('forceRerender', this.forceRerender)
in the created hook. The LiteratureReview component executes its forceRerender() function, which includes
axios.get('/quote').then(response => this.quotes = response.data)
.

Modal

<script>
    export default {
        props: ['target'],
        methods: {
            submit() {
                this.$emit('submit')
                this.$root.$emit('forceRerender')
            }
        }
    }
</script>

Literature Review Component

<script>
    import {
        app
    } from '../app.js'
    import {
        store
    } from '../app.js'

    export default {
        props: ['loop', 'literature_review_id', 'topic', 'type', 'year', 'link'],
        data() {
            return {
                quotes: app.quotes,
                sharedObject: store,
            }
        },
        created() {
            this.$root.$on('forceRerender', this.forceRerender)
        },
        methods: {
            filterByLiteratureReview(quotes, literature_review_id) {
                return this.quotes.filter(quote => quote.literature_review_id == literature_review_id)
            },
            updateLitIdForAddingQuote(value) {
                this.sharedObject.setLiteratureReviewIdAction(value)
            },
            forceRerender() {
                axios.get('/quote').then(response => this.quotes = response.data)
            }
        }
    }
</script>

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

Could anyone provide guidance on how to bypass the same origin policy effectively while working with Dashcode? I'm feeling a bit confused

After exploring various recommendations on overcoming the same-origin policy, I am still unsure about the best approach to take when working with dashcode. If you have any insights or tips on how to successfully implement this, please share them! ...

Adjusting the background color of a MuiList within a React Material-UI Select component

Looking to customize the background color of the MuiList in a react material-ui Select component without affecting other elements. Specifically targeting the Select element with the name 'first'. Despite setting className and trying different cl ...

Struggling to decode the JSON data from a Rails server using Javascript

I am currently facing difficulties parsing JSON data from my Rails server using Javascript. While I have a good amount of experience with Rails, I am fairly new to JS and keep encountering an unknown error. It would be extremely helpful if someone could g ...

Sending an associative array to Javascript via Ajax

Learning a new programming language is always a great challenge. Can someone guide me on how to efficiently pass an associative array to JavaScript using AJAX? Below is a snippet of code from server.php: $sql = "SELECT Lng, Lat, URL FROM results LIMIT ...

Exploring the isolate scope within a compiled directive

I successfully managed to compile a directive using this piece of code: let element, $injector, $compile, link, scope; element = angular.element(document.getElementById(#whatever)); $injector = element.injector(); $compile = $injector.get('$compile& ...

Encountering an error with npm run dev following the installation of Bootstrap

After following a tutorial on vue and laravel, I made some progress. Things were going smoothly, and I even successfully implemented my first vue-component. However, when I tried to install bootstrap, everything went downhill. Now I am encountering the fo ...

How can I eliminate unwanted zombie events in Vue JS?

How do you get rid of a zombie event? When navigating back and forth, the events run multiple times. MainApp.vue <template> <input type="button" @click.prevent="handleClick()" value="Click Me"> </template> <script> export defa ...

Flask integration with AJAX for a HTML range slider

I'm currently facing a challenge with my HTML control panel that features an array of buttons and sliders. While the buttons are fully functional and trigger post requests that are received and executed by my Python app, I'm encountering issues w ...

Storing and Editing Collection of Elements

My latest project involves creating a basic web scraping tool that gathers information on apartment prices from a specific webpage. Each time the tool runs, it compiles an array of objects with details such as date, time, floor plan name, bed number, floor ...

Displaying or concealing dropdown menus based on a selected option

My goal is to have a drop-down menu in which selecting an option triggers the display of another drop-down menu. For example, if I have options like "Vancouver," "Singapore," and "New York," selecting Vancouver will reveal a second set of options, while ch ...

Utilizing a string as an argument in a function and dynamically assigning it as a key name in object.assign

Within my Angular 5 app written in TypeScript, I have a method in a service that requires two arguments: an event object and a string serving as the key for an object stored in the browser's web storage. This method is responsible for assigning a new ...

Utilizing npm scripts to compress all HTML files within a directory, including its subdirectories

I am looking for a way to compress all the files with a .html extension in a particular folder, including any subfolders, using a script called npm run. Ideally, I would like the original .html files to be replaced with the minified versions, but creating ...

What is the correct placement for $.validator.setDefaults({ onkeyup: false }) in order to deactivate MVC3 onKeyup for the Remote attribute?

After coming across various solutions on how to disable the onKeyup feature of MVC3 Remote Validator, I noticed that many suggest using the following code: $.validator.setDefaults({ onkeyup: false }); However, I'm in a dilemma about where to place t ...

What could be causing issues with my setup for submitting forms in Django and using jQuery AJAX?

Although I have encountered questions like this numerous times before, I am struggling to make my AJAX form function correctly using jQuery on the client side and Django on the server side. Despite researching extensively, I have not come across a step-by- ...

Chrome fails to read font family correctly

I created a jsfiddle that demonstrates an interesting behavior with setting and reading the font-family using jQuery. When I set the font-family to "Arial . . ." it reads back okay, enclosed in a single set of double quotes. However, when I set the font-fa ...

Preserving the Selected Date on the Calendar Even After the PHP Variable is Passed

I am currently using the calendar code below with a slight modification that I implemented. However, I have encountered an issue where when I select a date, the calendar successfully highlights the selected date. But once I pass this selected date along ...

Activate CSS element with a click

Is there a way to add a click event to a CSS class so that when it is clicked, it changes to a different class? I am specifically looking to change the character class on li items when they are clicked. Here is the code snippet: <!DOCTYPE html> <h ...

Having dual fixed navigation bars on a single webpage

I am looking to create two fixed navigation bars, one at the top and another in the center of the page. The idea is that when scrolling reaches the second nav bar, the first one should hide (or become relative) and the second one should become fixed. Then, ...

Perform a function within another function in Vue

I am dealing with two nested functions in Vue. The parent function needs to retrieve the value of an attribute, while the child function is responsible for using this attribute value to make an API call. How can I ensure that both parts are executed simult ...

Tips for preparing data prior to downloading it as a CSV file

Trying to export data as a CSV file, encountering an issue with the generated file content: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[ ...