Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

KalimeroMK's avatar

Reload page in Vue.js

This is my component and when I click on generate button key is generating but is not showing until I press refresh how to fix it or to reload the page on click

<template>
    <div class="text-center">
        <div class="checkbox">
            <label>
                <input type="checkbox" v-model="toggle" :disabled="user.google2fa_secret"> {{ toggletext }}
            </label>
        </div>

        <hr>
        <div v-if="toggle">
            <div v-if="user.google2fa_secret">
                <p v-if="user.google2fa_secret">Your 2FA Secret Key</p>
                <h3>{{ user.google2fa_secret }}</h3>

                <button class="md-button md-raised md-accent" @click="disable">{{ disabletext }}</button>

                <p>Instructions for first time setup:</p>
                <p>Please install the <a :href="google_link">Google Authenticator</a> first.</p>
                <p>
                    You can install it from the
                    <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en">Google
                        Play</a> or
                    <a href="https://apps.apple.com/us/app/google-authenticator/id388497605">Apple Store</a>.
                </p>

                <p>Scan The QR code:</p>
                <img :src="qr_code" alt="qr_code"/>
                <br>

                <form action="/google2fa/authenticate" method="POST">
                    <input type="hidden" v-model="csrf" name="_token">
                    <input name="one_time_password" type="text">

                    <button type="submit">Authenticate</button>
                </form>


            </div>

            <div v-else>
                <button class="md-button md-raised md-accent" @click="generate">{{ generatetext }}</button>
            </div>
        </div>

        <div v-else>
            <p>You don't have the 2FA enabled.</p>
        </div>


    </div>

</template>

<script>
    import axios from 'axios';

    export default {
        name: "TwoFactorAuth",
        props: {
            qr: {
                type: String,
                required: false,
                default: '',
            },
            user: {
                type: Object,
                required: true,
            },
            toggletext: {
                type: String,
                required: true,
            },
            generatetext: {
                type: String,
                required: true,
            },
            disabletext: {
                type: String,
                required: true,
            },
        },
        data() {
            return {
                toggle: !!this.user.google2fa_secret,
                google_link: 'https://www.google.com/landing/2step/',
                qr_code: this.qr,
                csrf: ''
            }
        },
        methods: {
            generate() {
                axios.post(`/api/user/${this.user.eid}/2fa`)
                    .then(res => {
                        this.user.google2fa_secret = res.data.secret;
                        this.secret = this.user.google2fa_secret;
                        this.qr_code = res.data.qr;


                    })
                    .catch(this.handleError);
            },
            disable() {
                axios.post(`/api/user/${this.user.eid}/2fa`, {disable: true})
                    .then(res => {
                        this.user.google2fa_secret = res.data.secret;
                        this.qr_code = '';
                        this.toggle = false;
                    })
                    .catch(this.handleError);
            }
        },
        mounted() {
            this.csrf = document.head.querySelector('meta[name="csrf-token"]').content;

        }
    }
</script>

<style scoped>

</style>
0 likes
8 replies
rodrigo.pedra's avatar
Level 56

As user is passed as a prop its properties are not reactive, so Vue won't update the UI if you try to change them..

Similar to what you do to qr and qr_code you should copy that value to a data property on creating and updating that:

<template>
    <div class="text-center">
        <div class="checkbox">
            <label>
                <!-- CHANGED HERE -->
                <input type="checkbox" v-model="toggle" :disabled="google2fa_secret"> {{ toggletext }}
            </label>
        </div>

        <hr>
        <div v-if="toggle">
            <!-- CHANGED HERE -->
            <div v-if="google2fa_secret">
                <!-- CHANGED HERE -->
                <p v-if="google2fa_secret">Your 2FA Secret Key</p>
                <!-- CHANGED HERE -->
                <h3>{{ google2fa_secret }}</h3>

                <button class="md-button md-raised md-accent" @click="disable">{{ disabletext }}</button>

                <p>Instructions for first time setup:</p>
                <p>Please install the <a :href="google_link">Google Authenticator</a> first.</p>
                <p>
                    You can install it from the
                    <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en">Google
                        Play</a> or
                    <a href="https://apps.apple.com/us/app/google-authenticator/id388497605">Apple Store</a>.
                </p>

                <p>Scan The QR code:</p>
                <img :src="qr_code" alt="qr_code"/>
                <br>

                <form action="/google2fa/authenticate" method="POST">
                    <input type="hidden" v-model="csrf" name="_token">
                    <input name="one_time_password" type="text">

                    <button type="submit">Authenticate</button>
                </form>


            </div>

            <div v-else>
                <button class="md-button md-raised md-accent" @click="generate">{{ generatetext }}</button>
            </div>
        </div>

        <div v-else>
            <p>You don't have the 2FA enabled.</p>
        </div>


    </div>

</template>

<script>
    import axios from 'axios';

    export default {
        name: "TwoFactorAuth",
        props: {
            qr: {
                type: String,
                required: false,
                default: '',
            },
            user: {
                type: Object,
                required: true,
            },
            toggletext: {
                type: String,
                required: true,
            },
            generatetext: {
                type: String,
                required: true,
            },
            disabletext: {
                type: String,
                required: true,
            },
        },
        data() {
            return {
                toggle: !!this.user.google2fa_secret,
                google_link: 'https://www.google.com/landing/2step/',
                qr_code: this.qr,
                google2fa_secret: this.user.google2fa_secret, // ADDED HERE
                csrf: ''
            }
        },
        methods: {
            generate() {
                axios.post(`/api/user/${this.user.eid}/2fa`)
                    .then(res => {
                        this.google2fa_secret = res.data.secret;  // CHANGED HERE
                        this.qr_code = res.data.qr;


                    })
                    .catch(this.handleError);
            },
            disable() {
                axios.post(`/api/user/${this.user.eid}/2fa`, {disable: true})
                    .then(res => {
                        this.google2fa_secret = res.data.secret; // CHANGED HERE
                        this.qr_code = '';
                        this.toggle = false;
                    })
                    .catch(this.handleError);
            }
        },
        mounted() {
            this.csrf = document.head.querySelector('meta[name="csrf-token"]').content;

        }
    }
</script>

<style scoped>

</style>
KalimeroMK's avatar

can you show me what I need to do is my second day with vue.js and need to debag this

rodrigo.pedra's avatar

My code has some comments on the changes.

In the <template> look for these comment:

<!-- CHANGED HERE -->

The changes are below each of these comments

On the <script> look for this comments:

// ADDED HERE

 // CHANGED HERE

The changes are in the same line as the comments.

KalimeroMK's avatar

Still noting show on generate how I see you have made a change on disable or I em wrong

KalimeroMK's avatar

this was the solution

                        this.$forceUpdate();  // Calling forceUpdate will only force the view to re-render.
rodrigo.pedra's avatar

Hi @kalimeromk sorry for the late response, had to leave for a while. If forgot to change a line inside the generate method.

I updated the snippet above and added a comment in the line.

Vue docs says you should avoid using $forceUpdate:

If you find yourself needing to force an update in Vue, in 99.99% of cases, you’ve made a mistake somewhere.

https://vuejs.org/v2/guide/components-edge-cases.html#Forcing-an-Update

If you try the updated solution and verify it works, please let me know.

KalimeroMK's avatar

thx man for the help and telling me the write way

1 like

Please or to participate in this conversation.