Welcome to Abdul Malik Ikhsan's Blog

Using Vue.compile() to activate Vue component’s data and method in Mezzio Application

Posted in Javascript, Mezzio, Tutorial PHP, Vue.js by samsonasik on June 6, 2020

In previous post, we already tried create an SPA application with template rendered via Fetch for XHR purpose. What if we want to call data or/and method in template? With v-html, we can’t! The way we can do is make it compiled with Vue.compile(). Let’s check the JS part:

createPage = (name, object = {}, methods = {}) => {
    return Vue.component('page-' + name, {
        data    : () => Object.assign({content: ''}, object),
        methods : methods,
        mounted () {
            (new Promise( (resolve) => {
                fetch(
                    this.$route.path,
                    {
                        method: 'GET',
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest',
                        }
                    }
                ).then(response =>  resolve(response.text()));
            })).then(result => this.content = result);
        },
        render : function (c) {
            if (this.content == '') {
                return;
            }

            return c(Vue.compile('<div>' + this.content + '</div>'));
        }
    });
}

const routes = [
    { path: '/', component: createPage('home'), meta: {
        title: 'Home'
    } },
    { path: '/about', component: createPage(
        'about',
        {
            name: 'Abdul Malik Ikhsan'
        },
        {
            hit: () => alert('This alert already proof that I am a web developer!')
        }
    ), meta: {
        title: 'About Me'
    } },
    { path: '/contact', component: createPage('contact'), meta: {
        title: 'Contact Me'
    } },
    { path: "*", component: createPage('404'), meta: {
        title: '404 Not Found'
    } }
];

const router = new VueRouter({
    routes,
    base: '/',
    mode: 'history',
    linkExactActiveClass: "active"
});

router.afterEach(to => document.title = to.meta.title);

vue = new Vue({
    router
}).$mount('#root');

In above JS, first, I create a createPage function that in 2nd parameter, can pass custom data besides the current content data, and in 3rd parameter, can pass custom methods definition. With content fetched that assigned to content data, finally, we use it in the Vue.compile() on render.

The another special part is in the template part, it requires to use this.$parent to get parent attribute/method. For example, on the ‘about’ page above, we need to get name data, and can call the hit method, we can do like the following:

<!-- src/templates/app/about-page.phtml -->
<h1>About Me</h1>
<p>
    I'm a web developer. My name is {{ this.$parent.name }}. <br />
    <button v-on:click="this.$parent.hit">Click this as a proof</button>
</p>

That’s it, now you can open the about page and can see like the following:

I uploaded the sample source code at github, if you need to see what the diff between my previous post and this, you can check this PR https://github.com/samsonasik/mezzio-vue/pull/1 😉

Refs:
https://vuejs.org/v2/api/#Vue-compile
https://vuejs.org/v2/guide/render-function.html#Functional-Components
https://stackoverflow.com/questions/51548729/vuejs-vue-app-render-method-with-dynamic-template-compiled-is-throwing-some/51552701

4 Responses

Subscribe to comments with RSS.

  1. david said, on June 9, 2020 at 9:11 pm

    I am new to this, so, naive questions. You’re actually serving, as in fetching from the server, markup that has Vue directives in it, right? That is really cool. There have been many times that I’ve wished PHP and Javascript could really communicate in both directions and this feels like it’s going in that direction.

    LIne 18, the c parameter, what is that exactly? I infer that it’s a function but where does it come from?

  2. […] Using Vue.compile() to activate Vue component’s data and method in Mezzio Application […]

  3. […] in previous JavaScript posts, I posted how to use Vue.js in Mezzio Application. Now, in this post, I will show you how to […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: