Search code examples
javascriptvue.jsvue-resource

call a component from another component in vue.js


I have an alert component like in this video: https://laracasts.com/series/learning-vue-step-by-step/episodes/21 And I have another component (Book). When a book was created how can I call Alert component in the success callback function like this:

<alert>A book was created successfully !!!</alert>

I am a newbie in using vue.js. Thank you for your help.

Updated: This is my code

submit: function () {
    this.$http.post('/api/books/add', {
        data: this.data,
    }).then(function (response) {
        // I want to use Alert component right here to notice to users.
    }, function (response) {
    });
}

Update 2: Alert Component

<template>
    <div class="Alert Alert--{{ type | capitalize }}"
         v-show="show"
         transition="fade"
    >
        <slot></slot>

        <span class="Alert__close"
              v-show="important"
              @click="show = false"
        >
            x
        </span>
    </div>
</template>

<script>

    export default {
        props: {
            type: { default: 'info' },
            timeout: { default: 3000 },
            important: {
                type: Boolean,
                default: false
            }
        },

        data() {
            return {show: true};
        },

        ready() {
            if (!this.important)
            {
                setTimeout(
                    () => this.show = false,
                        this.timeout
                    )
            }

        }
    }

</script>

<style>
    .Alert {
        padding: 10px;
        position: relative;
    }

    .Alert__close {
        position: absolute;
        top: 10px;
        right: 10px;
        cursor: pointer;
    }

    .Alert--Info {
        background: #e3e3e3;
    }

    .fade-transition {
        transition: opacity 1s ease;
    }

    .fade-leave {
        opacity: 0;
    }
</style>

And in Book.vue I want to do like this:

// resources/assets/js/components/Book.vue
<template>
    .....
    <alert>A book was created successfully !!!</alert>

    //Create book form
    ....
</template>

<script>
    export default {
        methods: {
            submit: function () {
                    this.$http.post('/api/books/add', {
                    data: this.data,
                }).then(function (response) {
                     this.$refs.alert
                }, function (response) {
                });
    }
</script>

Solution

  • this JSfiddle does what you're looking for: https://jsfiddle.net/mikeemisme/s0f5xjxu/

    I used a button press rather than a server response to trigger the alert, and changed a few method names, but principle is the same.

    The alert component is nested inside the button component. Button passes a showalert prop to the alert component with the sync modifier set.

     <alert :showalert.sync="showalert" type="default" :important="true">A book was saved successfully</alert>

    Press the button, showalert is set to 'true', 'true' passed to alert as prop, alert displays as v-show condition is now true,

    data() {
              //by default we're not showing alert.
              //will pass to alert as a prop when button pressed
              //or when response from server in your case
              return {
                showalert: false
              };
            },

    a watch on the showalert prop in alert component sees a change and triggers a method that sets showalert back to 'false' after whatever many seconds set in timeout property.

                //this method is triggered by 'watch', below
                //when 'showalert' value changes it sets the timeout
                methods: {
                  triggerTimeout: function() {
                    //don't run when detect change to false
                    if (this.showalert === true) {
                      setTimeout(
                        () => this.showalert = false,
                        this.timeout
                      )
                    }
                  },
                },
    
                watch: {
                  // detect showalert being set to true and run method
                  'showalert': 'triggerTimeout',
                }

    Because this prop is synched back to parent, button state updated too.

    It works but using watch etc. feels overblown. Vue may have a better way to handle this. I'm new to Vue so somebody with more knowledge might chime in.