0

I have a Vue component that generates a dynamic component, and within that dynamic component is a click handler for a button that makes an Ajax call. Upon the Ajax call being successfully completed, I want to inform the component that generates the dynamic component that the Ajax call has finished. How do I do that?

The basic structure of the code in question is as follows:

<template>
    <div>
        <!-- Other markup here. -->
        <div class="contentPlaceholder">
        </div>
    </div>
</template>

<script>
    export default {
        // Props, etc.
        data: function () {
            return {
                // ...
                content: 'long-html-string-that-contains-Vue-components'
            };
        },
        mounted: function () {
            Vue.component(`content-component`, {
                template: `
                    <div class="content">
                        ${this.content}
                    </div>
                `,
                data: function () {
                    return {
                        // Local data here.
                    };
                }
                methods: {
                    // Button in this.content markup clicked.
                    btnCicked: function () {
                        ajax.post('url', {
                            // Params
                            success: () => {
                                // Want to report back to the parent component
                                // that we're here now.
                            }
                        });
                    }
                }
            });

            const res = Vue.compile(`
                <content-component>
                </content-component>
            `);

            new Vue({
                render: res.render,
                staticRenderFns: res.staticRenderFns
            }).$mount(`.contentPlaceholder`);
        }
    }
</script>

My initial thought was to do this.$emit('btnClicked', 'data-here') in the Ajax success callback, but when I try to attach an @btnClicked event handler to the content-component in either the template part of the Vue.component method call or the Vue.compile method call, I get a Vue error.

Basically, I have no clue what to do. The this context is definitely different in the dynamic component, so I can't just add a data property to the parent component and then set it in the Ajax callback of the dynamic component. I tried that and it doesn't work.

I trust there is a simple way to do this, but I'm honestly not sure how. Any help would be greatly appreciated. Thank you.


Edit: It's worth noting that I tried to treat the dynamic component as if it were just a regular child component of the parent component. As such, I added a this.$emit('btnClicked') call within the Ajax success callback and then added an @btnClicked handler to the content-component, but it didn't work.

Maybe I'm just doing it wrong, but I tried both of the following:

template: `
    <div class="content" @btnClicked="btnClicked">
        ${this.content}
    </div>
`,

// And

const res = Vue.compile(`
    <content-component @btnClicked="btnClicked">
    </content-component>
`);

But neither seem to work. Thanks.

HartleySan
  • 7,404
  • 14
  • 66
  • 119
  • Possible duplicate of [How can I update data from parent component when I click child component on the vue component?](https://stackoverflow.com/questions/45108107/how-can-i-update-data-from-parent-component-when-i-click-child-component-on-the) – Chetan Naik Aug 15 '19 at 18:27

1 Answers1

1

btnCicked: () => { console.log(this) }.

Try to use arrow function to save the context.

Another option is to create a function that already has access to outer this, and invoke it in your method.

const method = () => {
  console.log('I have access to outer this', this)
}
...
btnCicked: function () { method(); console.log('Local this', this) }
...
Andrew Vasylchuk
  • 4,671
  • 2
  • 12
  • 30
  • That's a good point, and I have edited my original question accordingly. Basically, I don't think I can do that because I have a data properties locally declared for the dynamic component as well, so I need to preserve the `this` for those methods. My bad. Are there any other ways? Thank you. – HartleySan Aug 15 '19 at 18:24
  • Yes, that works. Feels a bit sloppy and un-Vue-like, but it works. I will stick with this for now, but still wondering if there's a better way to do this with emitting or whatever. Thanks. – HartleySan Aug 15 '19 at 18:40
  • 1
    @HartleySan, What about EventBus? :) – Andrew Vasylchuk Aug 15 '19 at 18:43
  • Yes, that's not a bad idea. Thank you. – HartleySan Aug 15 '19 at 18:45
  • Then, I will edit my answer appropriately tomorrow. – Andrew Vasylchuk Aug 15 '19 at 18:47