murday1983
murday1983

Reputation: 4016

Cannot read property 'focus' of undefined in VUE When setting focus to button

I am new to vue I have component which if the endpoint fails, calls my generic 'Error' modal. All this is working fine but I keep getting the following error:

Cannot read property 'focus' of undefined

This only happens for the else part of my method function.

For this specific issue is I my 'failedPrcess' equals any of the following, this is when I get is, all others are fine:

Code

<template>
    <div class="modal fade danger-modal" id="errorModal" tabindex="-1" role="dialog" aria-labelledby="errorModalTitle" aria-hidden="true"
            data-keyboard="false" data-backdrop="static" style="z-index: 99999">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content danger-modal-content">
                <div class="modal-header danger-modal-headerfooter">An error has occurred</div>
                <div class="modal-body">
                    <p v-if="failedProcess === 'appGetAccount' || failedProcess === 'existOrderSearchProdOrders' || failedProcess === 'stockSearchStockLevels'
                            || failedProcess === 'cartFetchCouriers'">
                        {{ contactTxt | capitalize }}
                    </p>
                    <p v-else-if="errorCount < 3">If the error continues, {{ contactTxt }}</p>
                    <p v-else>As the error has continued, {{ contactTxt }}</p>
                    <p>
                        <b>
01234 567890
                            <br />
Open from 00:00 to 07:00
                        </b>
                    </p>
                    <p>Advising of what you were doing when the error occurred.</p>
                </div>
                <div class="modal-footer danger-modal-headerfooter">
                    <a v-if="failedProcess === 'appGetAccount'" ref="logoutButton" class="btn btn-primary" :class="logoutButtClicked" @click="logoutClicked = true" href="/site/logout">
                        <span v-if="!logoutClicked" id="logoutButtonLabel">Logout</span>
                        <span v-else id="logoutSpinner">
                        <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
                            Logging out
                        </span>
                    </a>
                    <router-link v-else-if="failedProcess === 'fetchOrderReportDetails'" to="/review" tag="button"
                                    ref="existOrdersButton" class="btn btn-primary" type="button" data-dismiss="modal" @click.native="closeButton">
                        Return to existing orders
                    </router-link>
                    <button v-else-if="errorCount < 3 && (failedProcess !== 'productsFetchProducts' && failedProcess !== 'existOrderSearchProdOrders'
                            && failedProcess !== 'stockSearchStockLevels' && failedProcess !== 'cartFetchCouriers')" ref="closeButton" class="btn btn-primary"
                            type="button" data-dismiss="modal" @click="closeButton">
                        Close
                    </button>
                    <router-link v-else to="/" tag="button" ref="homeButton" class="btn btn-primary" type="button" data-dismiss="modal" @click="closeButton">
                        Return to homepage
                    </router-link>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import * as params from '../params';

export default {
    name: "ErrorModal",

    data() { 
        return {
            contactTxt: 'please contact us on:',
            errorCount: 0,
            failedProcess: '',        
        }
    },

    mounted() {
        VueEvent.$on('show-error-modal', (failedProcess) => {
            if (this.failedProcess !== failedProcess) {
                this.errorCount = 0;
            }

            this.failedProcess = failedProcess;

            $('#errorModal').modal('show').on('shown.bs.modal', this.focus);
        });
    },

    methods: {
        focus() {
            if (this.failedProcess === 'appGetAccount') {
                this.$refs.logoutButton.focus();
            } else if (this.failedProcess === 'fetchOrderReportDetails') {
                this.$refs.existOrdersButton.$el.focus();
            } else if (this.errorCount < 3 && this.failedProcess !== 'productsFetchProducts') {
                this.$refs.closeButton.focus();
            } else {
                this.$refs.homeButton.$el.focus();
            }
        },
    }
}
</script>`enter code here`

Upvotes: 1

Views: 2966

Answers (1)

Guilherme Barboza
Guilherme Barboza

Reputation: 652

I've tried using v-if before and I also had similar problems and the best solution I found was, instead of using v-if/v-else-if/v-else, use v-show instead to perform conditional rendering.

Also, as the Vue.js doc says:

Generally speaking, v-if has higher toggle costs while v-show has higher initial render costs. So prefer v-show if you need to toggle something very often, and prefer v-if if the condition is unlikely to change at runtime.

Upvotes: 3

Related Questions