Skip to content
Advertisement

Call method from component inside component’s

I’m learning Vue.js and I’m struggling to find a way to organize my code. I’m trying to make everything as modular as possible, so when making a slider i did the following:

<template>
    <div class="banners">
        <slot></slot>
    </div>
</template>
<script>
    export default {
        methods: {
            echo() {
                console.log('Echoing..')
            }
        },
        mounted() {
            $('.banners').slick();
        }
    }
</script>

And in my view I simply use the component:

<banners>
    <?php for ($i = 0; $i < 5; $i++) : ?>
        <img src="http://lorempixel.com/1440/500" alt="Banner image" class="banner">
        <a href="#" v-on:click="echo">Echo</a>
    <?php endfor; ?>
</banners>

But after I try to call echo, it looks for it in the parent scope, not in the banners component scope, and says the method is not defined.

I’d like to know the best way to implement this. It’s useless for me to declare the method inside the parent scope because I will have millions of other methods throughout my project that that will be similar to this case, if I do that it will rapidly become unorganized. I want to have these banners methods inside their own whatever, so that I can easily find them all in their due place, as well as other modules aside from banners.

Maybe I’m using components the wrong way and should not be using for this? I just can’t put an echo() method inside the parent scope for something that is only related to that particular component. Imagine that maybe I will have other echo() in other element that will do something different from the banner’s one.

I also can’t move the slot content inside the template because I need to get the data via PHP, that’s why I did the for inside the slot.

Advertisement

Answer

In this particular situation you should use a scoped slot.

In your component pass the properties that you want to be able to use in the slot (in this case the echo method).

<div class="banners">
    <slot :echo="echo"></slot>
</div>

In your app template, wrap the content you are injecting into the slot with a template tag that has the scope property.

<banners>
    <template slot-scope="props">
    <?php for ($i = 0; $i < 5; $i++) : ?>
        <img src="http://lorempixel.com/1440/500" alt="Banner image" class="banner">
        <a href="#" v-on:click="props.echo">Echo</a>
    <?php endfor; ?>
    </template>
</banners>

Here is an example.

You can also destructure the scoped properties if you don’t need to use everything passed to the slot or just to avoid writing props.echo each time.

<banners>
    <template slot-scope="{echo}">
    <?php for ($i = 0; $i < 5; $i++) : ?>
        <img src="http://lorempixel.com/1440/500" alt="Banner image" class="banner">
        <a href="#" v-on:click="echo">Echo</a>
    <?php endfor; ?>
    </template>
</banners>
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement