This example is importing vue via a cdn link in a shopify site. The typical way of using vue like this is to create a vue app for a certain part of the page, so the below example assumes we are on a product page. What I am struggling with is that inside a certain function, for example openModal
, we might want some vue code inside the function but this code will not be compiled.
For example:
<div id="main">
<div class="header"></div>
<!-- Mount the vue app here -->
<div class="product-wrapper">
<button @click="openModal">open modal</button>
</div>
<div class="footer"></div>
</div>
<script type="module">
const { createApp } = Vue
const product_app = Vue.createApp({
compilerOptions: {
delimiters: ['{', '}']
},
data() {
return {
sizeOptions: ['xs', 's', 'm']
}
},
methods: {
openModal() {
// append modal to the DOM
// ...
const modal_inner = document.querySelector('.modal-inner')
// vue template code
// this of course will not be compiled by vue
const modal_content = `
<div v-for="size in sizeOptions"
class="sizeSwatch"
>{ sizeOption }</div>
`;
modal_inner.insertAdjacentHTML('beforeend', modal_content)
}
}
})
product_app.mount(document.querySelector('.product-wrapper'))
</script>
Since this is not in a vue app, and there is no build step, the above example is usually solved like this – wherein the vue template code we need for later is rendered in the app in a wrapper div with the display set to none, later we just clone it.
<div id="main">
<div class="header"></div>
<!-- Mount the vue app here -->
<div class="product-wrapper">
<button @click="openModal">open modal</button>
<div class="hidden">
<div v-for="size in sizeOptions"
class="sizeSwatch"
>{ sizeOption }</div>
</div>
</div>
<div class="footer"></div>
</div>
My idea was to do something like this but I don’t know how to do this and that is what this question is about, if the below example can be made to work.
<div id="main">
<div class="header"></div>
<!-- Mount the vue app here -->
<div class="product-wrapper">
<button @click="openModal">open modal</button>
</div>
<div class="footer"></div>
</div>
<script type="module">
const { createApp } = Vue
const product_app = Vue.createApp({
compilerOptions: {
delimiters: ['{', '}']
},
data() {
return {
sizeOptions: ['xs', 's', 'm']
}
},
methods: {
openModal() {
// append modal to the DOM
// ...
const modal_inner = document.querySelector('.modal-inner')
const modal_content = h(
'div',
this.sizeOptions.map(sizeOption) => {
return h('div', sizeOption)
})
)
// somehow append the vnode to the modal
}
}
})
product_app.mount(document.querySelector('.product-wrapper'))
</script>