2

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.

2 Answers 2

2

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>

Sign up to request clarification or add additional context in comments.

8 Comments

could php include a <script> to mount another instance of the same vue app and use the same components further down the dom tree? (the same components have already been parsed and are working further up).
@Brad You can achieve that by using Vue compile option. I updated the answer. Hope that will work as per your expectation.
Not sure if we are on the same page yet. Template is not coming from PHP, the entire vue component is already compiled and available inside the app. The PHP content just wants to use components that already exist.
@Brad I understand that. If you see template contains the Cats component and it renders properly.
Hey, m8 I upvoted but haven't accepted it yet because I cant get it to work. I don't think it's your code tho I think its something funky with the legacy mish-mash of a setup I have inherited.
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.