I’m working on a Vue 3 project where I need to dynamically replace anchor elements that contain a specific attribute (data-button) with a custom Vue component (CustomButton). To achieve this, I created a directive that queries all the anchor tags within a specified element and dynamically imports the CustomButton component. Below link is a simplified version of my implementation:
[you can see a simiplified example here]
Directive (parser-directive.js):
import { nextTick } from 'vue';
import { loadCustomButton } from './dynamic-import-custom-button.js';
const htmlParserDirective = {
async mounted(el) {
await nextTick();
console.log('Directive inserted');
const wrapper = document.createElement('div');
wrapper.innerHTML = el.innerHTML;
const anchorTags = wrapper.querySelectorAll('a[data-button]');
if (anchorTags.length) {
for (const anchor of anchorTags) {
const text = anchor.innerText.trim();
const path = anchor.getAttribute('data-path');
const CustomButton = await loadCustomButton();
console.log('CustomButton loaded:', CustomButton);
const CustomButtonComponent = createApp(CustomButton, { text, path });
const customButtonInstance = CustomButtonComponent.mount(document.createElement('div'));
console.log('CustomButton instance mounted:', customButtonInstance);
customButtonInstance.$el.addEventListener('mouseenter', () => {
console.log('Mouse Enter');
});
customButtonInstance.$el.addEventListener('mouseleave', () => {
console.log('Mouse Leave');
});
anchor.parentNode.replaceChild(customButtonInstance.$el, anchor);
}
el.innerHTML = wrapper.innerHTML;
}
},
};
export default htmlParserDirective;
CustomButton.vue:
<a :href="path">
{{ text }}
</a>
</template>
<script>
export default {
name: 'CustomButton',
props: {
text: {
type: String,
default: '',
},
path: {
type: String,
default: ''
}
},
mounted() {
console.log('CustomButton mounted');
},
};
</script>
<style scoped>
a {
text-decoration: none;
color: inherit;
cursor: pointer;
}
</style>
App.vue:
<div id="app">
<div v-html-parser>
<a href="#" data-button data-path="test.test">Test Button</a>
</div>
</div>
</template>
<script>
export default {
name: 'App',
};
</script>
Problem:
The issue I’m facing is that the event listeners for mouseenter and mouseleave are not being triggered. Although I can see that the CustomButton component is loaded and replaced correctly, the added event listeners do not seem to be working.
Question:
Why are the mouseenter and mouseleave event listeners not being triggered on the dynamically created CustomButton component? Is there a different approach or a solution to ensure these event listeners are called?
Any help or suggestions would be greatly appreciated!
>Solution :
You just set pure HTML to the directive’s div. That copies HTML only obviously, no event handlers, you should move the children elements:
el.innerHTML = '';
for(const child of wrapper.children){
el.appendChild(child);
}