I have recently been working on a WordPress Plugin that has a single Vue Component. This plugin is complied by Webpack and renders to the page when using a shortcode. The only issue I am getting is when performing a method, I get an error mentioning "Invalid VNode type": Symbol(Fragment)
My current WordPress Theme is also using Vue, and how we configured our plugin is too use the main Vue instance in our theme. The theme is also being complied by Webpack.
In our theme, we create an event and an empty array on the window.
window.registerComponents = new Event('registerComponents');
window.vueComponents = [];
In our plugin, we are checking for the event, and then add the Vue components to an empty array.
if(window.registerComponents){
window.addEventListener('registerComponents', function (e) {
for (const [name, component] of Object.entries(components)) {
window.vueComponents.push(component);
}
});
}
In our theme, we then loop through these components and then register them on the main Vue instance.
window.vueComponents.forEach(component => main.component(component.name, component));
The component renders, however I receive the VNode error when adding a V-For.
<template>
<div class="search-container">
<form class="search-bar" role="search" method="post">
<div class="input-wrapper">
<input @keyup="queryFinder" type="search" class="search-field" placeholder="Search Products"
name="s"
title="Search Products"
autocomplete="off"
>
<button type="submit" value="Search">
</button>
</div>
</form>
<div :class="[showResults ? 'active results-wrapper' : 'results-wrapper']">
<div v-if="spinner" class="loader"></div>
<div v-else class="results">
<ul v-if="results.length > 0">
<li v-for="result in results">{{result.id}}</li>
</ul>
<ul v-else>
<li>Sorry, no results found. Try again.</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'search-bar',
data() {
return {
inputField: '',
showResults: false,
results: [],
spinner: false,
}
},
watch: {
inputField(val){
val.length === 0 ? this.showResults = false : this.showResults = true;
}
},
methods: {
queryFinder(e) {
const value = e.target.value.toLowerCase();
this.spinner = true
this.inputField = value;
const URL = `TEST_URL`;
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
this.timer = setTimeout(() => {
axios.get(URL).then(res => {
this.results = res.data
console.log(res.data)
this.spinner = false
}).catch(err => {
console.log(err);
})
}, 800);
},
},
mounted() {
console.log("Test component mounted!");
}
}
</script>
<style lang="scss">
.search-container {
position: relative;
.results-wrapper {
&.active {
display: block !important;
}
display: none;
position: absolute;
width: 100%;
min-height: 200px;
background-color: #0083C1;
overflow: scroll;
.loader {
position: absolute;
left: 40%;
top: 35%;
border: 16px solid #fff;
border-top: 16px solid #0083C1;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 2s linear infinite;
}
ul {
list-style: none;
padding: 15px;
margin-bottom: 0;
li {
color: #fff;
padding: 10px;
cursor: pointer;
&:hover {
background-color: #6AC0E0;
}
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
}
</style>
Moving the component to the theme, and rendering seems to fix the issue. However, we would like to keep this as separate as possible. I have tried changing the Webpack Config with little success. Adding symlinks, changing Vue location, etc. Any help would be greatly appreciated!