Problem
I have a BaseFormControl
component which accepts id
prop. It sets id
prop value as both for
attribute value on <label>
element and id
attribute value on a given input. As I want BaseFormControl
to be a generic component re-usable with various input types, I pass the input as a slot. The code for the component below:
<script>
export default {
props: {
id: {
type: String,
required: true
}
}
};
</script>
<template>
<div>
<label :for="id">
<slot name="label" />
</label>
<slot
name="input"
:id="id"
/>
</div>
</template>
The problem with this approach is that <slot>
doesn't pass any attributes to the slot contents, so :id
isn't passed to the actual input at all.
So I tried setting it programatically:
export default {
props: {
id: {
type: String,
required: true
}
}
created() {
let inputSlot = this.$slots.input;
if (inputSlot) {
inputSlot[0].data.attrs.id = this.id;
}
}
};
It works perfectly in some cases (input passed as a slot has id
attribute set properly in it's HTML), but in others it doesn't. What's especially interesting is that all the input components (what I put in the input slot is another base component, not a generic <input>
tag) actually have it's this.$attrs
properly populated with id
, but sometimes it appears in actual HTML and sometimes it does not.
Can someone explain me that behavior, tell me what I'm doing wrong and how to solve that case?
Pen
I created a pen to illustrate the concepts. The only problem is in the pen everything works fine. In my app out of 2 selects on the page, only 1 has id
set properly - the other one is rendered without id
at all (though id
is set in it's this.$attrs
).
What yoou are doing is passing
id
to the slot as slot data. Which means you are creating a scoped slot.You can access this data in the
BaseFormControl
using theslot-scope
attribute.PS:
if you are passing
id
as a prop you can directly use it to set the id of the input as below