Brad
Brad

Reputation: 950

Using VueJS components in PHP

I want to mix basic HTML generated by Php and VueJS components without having to use VueJS all the way down to the lowest dom leaf.

The parent layout has the Vue app applied all the headers navs assides etc are Vue components and the main content on most pages are still plain HTML generated by PHP.

I want to upgrade small parts of the main content with Vue components but I cant use them once HTML has been used:

Php script generates the entire dom
<div id="app"> VueJS instance mounts here.
    <Cats>This component works perfectly here.
    <div id="main Content">More HTML content generated by PHP.
        <Cats> Cats does nothing here.

<Cats> works perfectly fine in the upper DOM but after rendering some basic HTML the app will no longer populate components further down.

Php can render JS in a script tag but it's unable to use any imports.

Is there any way to get the Vue instance to treat all <Cats> tags as the Cats component regardless of where it is written on the page?

So far I have tried:

Any ideas?

EDIT: The things I tried previously may be been blocked by the mishmash of multiple UI modernization attempts in this monolith I have inherited. So I would not rule those out for others facing this situation.

Upvotes: 2

Views: 5179

Answers (2)

Brad
Brad

Reputation: 950

In the end, I had to manually add a JS file to the build configs containing a global window.ExtraVue with a setup function like so:

import Cats from 'files/Cats.vue';
window.ExtraVue = {
    setup: function(data) {
        new Vue({
            el: '#extra-vue',
            data: data,
            components: {
                Cats
            },
            template: '<Cats/>'
        })
    }

};

The setup function is then called at the very end of the PHP script.

<script>window.ExtraVue.setup(<?=json_encode($array)?>)</script>

The setup function can now create a new Vue instance for each component that needs to be out on its own.

Ideally, it would be great if VueJS could just replace matching tags with components.

Upvotes: 0

Roh&#236;t J&#237;ndal
Roh&#236;t J&#237;ndal

Reputation: 27232

If you are dynamically passing the template which is coming from an API or from any other source into your Vue instance. There is a way to access that via v-html attribute but before using that please have a look at note below.

Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates.

Hence, As you are trying to bind/render the Component itself and it's not a plain HTML. So it will not processed by Vue's template compiler.

Possible solution is that you can get a component name and props from your PHP API instead of whole HTML template.

You can also achieve the same by using Vue compile option. Here is the demo :

Vue.component('Cats', {
  props: ['msg'],
  template: '<h3>{{ msg }}</h3>'
});

// Template coming from PHP
const template = `<div id="main Content"><Cats msg="Meow... Meow..."></div>`

var app = new Vue({
  el: '#app',
  data: {
    compiled: null
  },
  mounted() {
    setTimeout(() => {
        this.compiled = Vue.compile(template);
    })
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <Cats msg="Meow...">
  </Cats>
  <component :is="compiled"></component>
</div>

Upvotes: 2

Related Questions