link3151 link3152 link3153 link3154 link3155 link3156 link3157 link3158 link3159 link3160 link3161 link3162 link3163 link3164 link3165 link3166 link3167 link3168 link3169 link3170 link3171 link3172 link3173 link3174 link3175 link3176 link3177 link3178 link3179 link3180 link3181 link3182 link3183 link3184 link3185 link3186 link3187 link3188 link3189 link3190 link3191 link3192 link3193 link3194 link3195 link3196 link3197 link3198 link3199 link3200 link3201 link3202 link3203 link3204 link3205 link3206 link3207 link3208 link3209 link3210 link3211 link3212 link3213 link3214 link3215 link3216 link3217 link3218 link3219 link3220 link3221 link3222 link3223 link3224 link3225 link3226 link3227 link3228 link3229 link3230 link3231 link3232 link3233 link3234 link3235 link3236 link3237 link3238 link3239 link3240 link3241 link3242 link3243 link3244 link3245 link3246 link3247 link3248 link3249 link3250 link3251 link3252 link3253 link3254 link3255 link3256 link3257 link3258 link3259 link3260 link3261 link3262 link3263 link3264 link3265 link3266 link3267 link3268 link3269 link3270 link3271 link3272 link3273 link3274 link3275 link3276 link3277 link3278 link3279 link3280 link3281 link3282 link3283 link3284

[Vue.js] Correct way to pass props to all children through slot-scope in Vue.js

Updated code in light of comments about slot-scope

Coming from React, when having a hard time understanding how vue.js uses slots and slot-scope to pass props to child components.

In my current project, there is a DataSlicer component that receives a data prop and performs some manipulation on it. I would then like to pass the manipulated data on to child components via <slot>. I understand that slot-scope is the way to do this but it seems to only work when the parent component tells a child to pass something to its own children — which seems to defeat the whole point (in terms of composition and separation of concerns).

This is what there is working right now, based on reading How to pass props using slots from parent to child -vuejs

App.vue

<DataSlicer
v-if=”data”
y-axis-dimension=”Subparameter”
x-axis-dimension=”Year”
value-dimension=”Total_Registrations”
:filters=”{}”
:data=”data”
\>
<template slot-scope=”childProps”>
<Chart :title=”title” :series-data=”childProps.slicedData” />
</template>
</DataSlicer>

DataSlicer.vue

<template>
<div>
<slot :slicedData=”slicedData”/>
</div>
</template>

My expectation was that I could define slot-scope on the <template> tag in DataSlicer.vue, but that doesn’t seem to work.

Am I missing something? I don’t understand why App.vue.js would need to know or care what DataSlicer is passing to its children. The problem is only compounded the more I split up my components (for example, if I stick DataSlicer inside another component to abstract the api calls, which are currently handled at the App.vue.js level, then App.vue.js also has to also tell that component to pass data on to its DataSlicer child[ren]).

Maybe when just stuck in React thinking here and there’s a different or better way to do this?

EDIT:

If it helps, I’m able to accomplish what using a render function like so:

render: function (createElement) {
return createElement(
‘div’,
this.$slots.default.map(vNode => {
if (vNode.componentOptions) {
vNode.componentOptions.propsData.slicedData = this.slicedData;
}
return vNode;
})
)
}

This feels rather hackish/fragile and also like I’m stretching vue.js to do something in the “react way” when there is probably a better approach.

Solution :

I could not really wrap my head around the code because you didn’t paste the complete code, but this should work this is a working example of slot-scoping in vuejs

//ParentComponent.vue

<template>
<div>
<child-component>
<template scope=”defaultSlotScope”>
<p>{defaultSlotScope.text}</p>
<!– Renders <p>I’ll get rendered inside the default slot.</p> –>
</template>
<template slot=”literally-the-best” scope=”bestSlotScope”>
<p>{bestSlotScope.text}</p>
<!– Renders <p>I’ll get rendered inside the *best* slot.</p> –>
</template>
</child-component>
</div>
</template>

<script>
import ChildComponent from ‘./ChildComponent.vue’;

export default {
components: {
ChildComponent
}
}
</script>

//ChildComponent
<template>
<div>
<p>Look, there’s a slot below me!</p>
<slot :text=”defaultSlotText”></slot>
<slot name=”literally-the-best” :text=”namedSlotText”></slot>
</div>
</template>

<script>
export default {
data() {
return {
defaultSlotText: “I’ll get rendered inside the default slot.”,
namedSlotText: “I’ll get rendered inside the *best* slot.”
}
}
}
</script>

I hope this would help