'How to reference text that's in '<slot></slot>' in Vue.js
How to reference text that's in in Vue.js?
Vue.component('component', {
template: `<button><slot></slot></button>`,
created: function() {
// i would like to access the text in slot here
}
});
Solution 1:[1]
Note: This answer applies to Vue v2 only.
The content inside the default slot, which is what you are describing, is exposed as this.$slots.default in the Vue. So the most naive way to get the text inside your button would be to use this.$slots.default[0].text.
Vue.component('component', {
template: `<button><slot></slot></button>`,
created: function() {
const buttonText = this.$slots.default[0].text;
}
});
The problem is that there may be more than one node inside the slot, and the nodes may not necessarily be text. Consider this button:
<button><i class="fa fa-check"></i> OK</button>
In this case, using the first solution will result in undefined because the first node in the slot is not a text node.
To fix that we can borrow a function from the Vue documentation for render functions.
var getChildrenTextContent = function (children) { return children.map(function (node) { return node.children ? getChildrenTextContent(node.children) : node.text }).join('') }
And write
Vue.component("mybutton", {
template:"<button><slot></slot></button>",
created(){
const text = getChildrenTextContent(this.$slots.default);
console.log(text)
}
})
Which will return all the text in the slot joined together. Assuming the above example with the icon, it would return, "OK".
Solution 2:[2]
Run the code snippet below that get the slot text passed by parent :
I'm using "ref" :
<span ref="mySlot">
this.$refs.mySlot.innerHTML
Careful : <slot ref="refName"></slot> don't works because <slot> are not render on html.
You have to wrap the <slot></slot> with <div></div> or <span></span>
The code :
Vue.component('component', {
template: '<button>' +
'<span ref="mySlot">' +
'Text before<br />' +
'<slot name="slot1">' +
'Text by default' +
'</slot>' +
'<br />Text after' +
'</span>' +
'</button>',
mounted: function() {
console.log( this.$refs.mySlot.innerHTML);
}
});
new Vue({
el: '#app'
});
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
<component>
<span slot="slot1">I'm overriding the slot and text appear in this.$refs.mySlot.innerHTML !</span>
</component>
</div>
Solution 3:[3]
For Vue 3.
The answer from @bert works well on Vue 2, but Vue 3 slots have a more complex structure.
Here is one way to get the slots text contents (from default slot) on Vue 3.
const getSlotChildrenText = children => children.map(node => {
if (!node.children || typeof node.children === 'string') return node.children || ''
else if (Array.isArray(node.children)) return getSlotChildrenText(node.children)
else if (node.children.default) return getSlotChildrenText(node.children.default())
}).join('')
const slotTexts = this.$slots.default && getSlotChildrenText(this.$slots.default()) || ''
console.log(slotTexts)
Solution 4:[4]
You can access the slot text by joining the innerText of all the children inside the slot.
getSlotText() {
return this.$slots.default.map(vnode => (vnode.text || vnode.elm.innerText)).join('');
},
Solution 5:[5]
My use case was pretty simple, I had a default slot with only text. Here's how I accessed the text in vue3 with script setup:
<script setup lang="ts">
import { computed, useSlots } from "vue";
const slots = useSlots();
const slotText = computed(() => {
return slots.default()[0].children; // This is the interesting line
});
</script>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Raine Revere |
| Solution 2 | Happyriri |
| Solution 3 | antoni |
| Solution 4 | Vitim.us |
| Solution 5 | Herobrine |
