work sarah
work sarah

Reputation: 79

Why does boostrap vue toaster dissapears immediately?

I am using Laravel + Vue.js to create a SPA. In the SPA, I am creating a form where user can write markdown content in it and click button to submit it. I want to show an error toaster at the bottom right corner of the screen if the user didn't input any content when they clicked the send button. I am using boostrap vue toast to implement the error toaster.

However, when I clicked the send button, the error toaster will just blink for 1 second and dissapear immediately. Also, the error toaster blinks at top left corner which is different from what I wrote in the code below.

The mixin that contains the method to invoke the toast:

ErrorMessage.vue

# ErrorMessage.vue
<script>
export default {
    methods: {
        showErrorMessage (msg) {
            this.$bvToast.toast(msg, {
                title: ["Error!"],
                variant: "danger",
                toaster: "b-toaster-bottom-right"
            });
        }
    }
};
</script>

I imported the above mixin in this vue component ArticleForm.vue.

ArticleForm.vue

<template>
    <form @submit.prevent="passArticleData">
        <div id="editor-markdown-editor">
            <div id="editor-markdown">
                <div
                    id="editor-markdown-tag-input"
                    @click="toggleTagModal"
                >
                    <ul v-if="insertedTags.length">
                        <li v-for="tag in insertedTags"
                            :key="tag.id"
                            class="tag"
                        >
                            {{ tag.name }}
                        </li>
                    </ul>
                    <span v-else>タグを入力してください</span>
                </div>
                <div id="editor-markdown-textarea">
                    <textarea :value="input" @input="update" ref="textarea"></textarea>
                    <div id="drop-here"></div>
                </div>
            </div>

            <div id="editor-preview">
                <article v-html="compiledMarkdown(input)" class="markdown-render" ref="articleHtml"></article>
            </div>
        </div>
    </form>
</template>

<script>
import _ from "lodash";
import ErrorMessage from "./mixins/ErrorMessage";
import { markdownTable } from "markdown-table";

export default {
    props: {
        article: Object,
        tags: Array
    },
    mixins: [ErrorMessage],
    data () {
        return {
            articleToPass: {
                title: "",
                body: "",
                isDraft: true
            },
            input: "",
            tagsToPass: [],
            insertedTags: [],
            tagModalOpen: false
        };
    },
    methods: {
        update: _.debounce(function (e) {
            this.input = e.target.value;
        }, 300),
        passArticleData (e) {
            // Get title from input
            try {
                this.articleToPass.title = this.$refs.articleHtml.getElementsByTagName("h1").item(0).innerHTML;
            } catch (e) {
                this.showErrorMessage(["Body md can't be blank"]);
            }

            // Remove first line(title) from users' input
            this.articleToPass.body = this.input.substring(this.input.indexOf("\n") + 1);

            // tag id of written article
            const tagIds = this.insertedTags.map(obj => obj.id);
            this.tagsToPass = tagIds;
            this.$emit("handle-new-data", this.articleToPass, this.tagsToPass);
        }
    
}

Parent component of the above vue component:

ArticleCreate.vue

<template>
    <div id="content-area">
        <header-component></header-component>
        <main id="editor-area">
            <article-form :article="article" :tags="tags" @handle-new-data="postArticle"></article-form>
        </main>
    </div>
</template>

<script>
import HeaderComponent from "./Header.vue";
import ArticleForm from "./ArticleForm.vue";

export default {
    data () {
        return {
            article: {
                title: "",
                body: "",
                is_draft: true
            },
            tags: []
        };
    },
    components: {
        HeaderComponent,
        ArticleForm
    },
    methods: {
        postArticle (articleObj, tagsData) {
            const data = { article: articleObj, tags: tagsData };
            axios.post("/api/articles", data)
                .then((res) => {
                    this.$router.push({ name: "article.show", params: { article: res.data } });
                });
        }
    }

};
</script>

I tried:

I have spent trying to solve this but failed. Does anyone know why is this happening and how can I make it work? Please let me know if you need any extra information. Thank you in advanced.

Upvotes: 1

Views: 722

Answers (2)

work sarah
work sarah

Reputation: 79

I have figured out the problem. The problem is that bootstrap-vue css is not loaded properly in my project. Just add import "bootstrap-vue/dist/bootstrap-vue.css"; to app.js and it works perfectly fine now. Thank you

Upvotes: 1

flx
flx

Reputation: 1578

As stated in this comment on stackoverflow that is usually a sign of a bootstrap version mismatch.

I was actually able to reproduce that issue and also fix it with rolling back to bootstrap v4


Broken with bootstrap 5

https://codesandbox.io/s/bootstrap-vue-toasting-broken-with-bootstrap-5-bqe2c

Working with bootstrap 4

https://codesandbox.io/s/bootstrap-vue-toasting-working-with-bootstrap-4-jk2jl

Upvotes: 1

Related Questions