Can you define provide/inject in a dynamic component in Vue3 without using the host setup function?

When working with a dynamic component in Vue3, I am setting up the props using v-bind. However, I am now interested in implementing the provide/inject feature to pass properties to the dynamic component. My dynamic component expects values provided for its child components through inject in the setup function.

<component :is='MyComponent' v-bind='myProps' />

Although not explicitly documented in Vue, I have attempted to pass my provided properties to the dynamic component like this:

<component :is='MyComponent' v-bind='myProps' :provide='myProvidedProps'/>

I also tried placing the provide object within the props object, but it did not work as expected.

Answer №1

Having delved into the Vue3 source code, it appears that there is no direct way to specify the provide spec for a dynamic component in the template itself. Instead, it must be invoked in the setup function or options of the parent component hosting the dynamic component, or within the setup or options of the dynamic component.

There are two possible approaches:

  1. Call provide on the component that hosts the dynamic component.
setup() {
  provide('message', 'hello')
}
<template>
  <component :is='myComponent' />
</template>

This method did not work for me as my setup function was executed before the activation of the dynamic component; besides, I needed to set both the component type and the provided value simultaneously.

  1. Pass the items to be provided into the component as props and let the dynamic component invoke provide on them.
function setComponent(someImportedComponent, providedValues) {
  myComponent.value = someImportedComponent
  myProps.value = {
    toProvide: providedValues
  }
}
<template>
  <component :is='myComponent' v-bind='myProps' />
</template>

MyComponent

setup() {
  for(let [key,value] of Object.entries(props.toProvide) ) {
    provide(key, value)
  }
}

However, this approach has its drawbacks as every dynamic component now needs to handle and invoke the passed-in provide items.

Solution 1

To circumvent each component needing awareness of the provided values, one can create an intermediary component that handles the provisioning of values.

Providable (Intermediate Component)

<script setup lang="ts">
import {provide} from 'vue'

const props = defineProps<{
  is: any
  provide?: Record<string, any>
  [key: string]: any
}>()

if (props.provide) {
  for (const [key, value] of Object.entries(props.provide)) {
    provide(key, value)
  }
}

const _props = Object.fromEntries(Object.entries(props).filter(it => {
  return it[0] !== 'is' && it[0] !== 'provide'
}))
</script>

<template>
  <component :is="is" v-bind="_props"/>
</template>

Usage example:

<template>
  <providable :is="myComponent" :provide='toProvide' v-bind='myProps' />
</template>

Solution 2

A more elegant solution involves creating a wrapper component, similar to how keep-alive operates. The target component is placed within the default slot.

Provide.vue

<script setup lang="ts">
import {provide} from 'vue'

const props = defineProps<{
  value: Record<string, any>
}>()

for (const [key, value] of Object.entries(props.value)) {
  provide(key, value)
}
</script>

<template>
  <slot name="default"/>
</template>

Usage example:

<template>
  <provide value='toProvide'>
    <my-component v-bind='myProps' />
  </provide>
</template>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Covering Vue methods with Jest and Coverage: a comprehensive guide

My goal was to improve the code coverage percentage by covering specific if statements within Vue methods. I am using package versions @vue/test-utils:"^1.1.4" and vue: "^2.6.12". Below is a snippet of my component: <template> <div :class=& ...

Guide on integrating the @nuxtjs/axios plugin with Nuxt3

I'm trying to fetch API data from using this code: <template> <div> </div> </template> <script> definePageMeta({ layout: "products" }) export default { data () { return { data: &apo ...

Differences Between Vuex Actions and Mutations

Can you explain the purpose of having both "actions" and "mutations" in Vuex? I comprehend the reasoning behind components not directly modifying state, but what is the advantage of introducing actions that trigger mutations to alter state? It seems like ...

When you make a POST request to an express API, the properties are not clearly defined

Just getting into Vue.JS and experimenting with creating a basic MEVN to-do list app for practice. I keep encountering an issue when trying to send a POST request to my express server, receiving the error message: TypeError: Cannot read properties of unde ...

Even after the destruction of the component in VUEJS, the logic inside the component continues to be

Within my component, I have implemented a while loop to continuously call an API every 3 seconds in order to check the status. async download() { while(true) //-> { await sleep(300); console.log("still executing"); const status = aw ...

Determine which scroll bar is currently in use

I'm running into an issue with multiple scrollbars on my page - they just don't seem to be functioning correctly: <div class="dates-container" v-for="id in ids"> <overlay-scrollbars :ref="`datesHeader` ...

What is the simplest way to incorporate Vue with Typescript, without the need for a complex build setup?

I've been spending the last couple of days experimenting with my basic ASP.NET Core website set up for Typescript 2.9, but unfortunately, I haven't made much progress. My main goal is to keep the front-end simple, with just single Vue apps on eac ...

What is the best way to transfer static assets from an npm package to a nuxt project?

Has anyone successfully sent assets from an npm package to a nuxt application before? I have a vue component within an npm package with the following structure: -src/ -assets/ -noun-filter.svg In this npm package, the vector image is included in the v ...

Adjusting the input label to be aligned inside the input box and positioned to the right side

I am currently working on aligning my input label inside the input box and positioning it to float right. The input boxes I am using have been extended from b4. Currently, this is how it appears (see arrow for desired alignment): https://i.stack.imgur.co ...

The recursive component is functional exclusively outside of its own scope

I'm facing an issue where my recursive component is not nesting itself properly. The problem arises when I try to use the Recursive component inside another Recursive component. Although the root is correctly inserted into the Recursive component fro ...

How can I enable a constant condition in eslint?

I have encountered an issue with my package.json configuration. Here is the current eslintConfig generated: "eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/essential", "@vue/standard" ...

Using a prop array as v-model in a Vue JS CheckBoxGroup implementation

Struggling to create a reusable CheckBoxGroup component with a prop array as v-model. I checked out the vuejs guide at https://v2.vuejs.org/v2/guide/forms.html#Checkbox which uses the v-model array in the data of the same component. However, this approach ...

Learn the process of sending both Header and Body data in a POST request using Axios with Vue.js

I'm currently attempting to call the post API of AWS Cognito's Token endpoint. The API functions perfectly when tested in my Postman client, but I am encountering issues when implementing it in my VueJS code. Here is a snippet of my code: test. ...

Adjust the attributes of v-data-table

I am working with a v-data-table and I need to create a method that can change the attribute "loading" to false within the method. Can anyone provide guidance on how to accomplish this? <v-layout fluid v-resize="onResize" child-flex> <v-da ...

Is it true that Laravel Sanctum only creates access tokens?

I am trying to grasp the essential flow of laravel sanctum within a SPA(vuejs) application. From what I have gathered so far: A middleware is set up for API authentication Upon user login, access_tokens are generated and sent back to the frontend. Th ...

Guide to displaying a template using Vue.js

Incorporating jQuery and vuejs version 2.3.4: https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js The code snippet below demonstrates my current setup: // Instantiating Vue. vueVar = new Vue({ el: '#content', ...

Using multiple 'template' tags in a single Vue file component

I work in a large company with a prominent frontend team, and my colleagues often use multiple template tags in single file components. This is a new practice to me, and I'm not sure if it's the best approach. However, when I questioned the head ...

Retrieving Vue component properties as a data type

I'm facing a dilemma with my Vue components. I want to extract the props from one component and use them as a type instead of a value in another component. Specifically, I have a component where I need to take in an array of props from a different com ...

Error in npm installation: expected version "0.15.7" but received an empty string on the new Vite project

After setting up a new vite project, I encountered an error while trying to run npm install. Node.js version: 16.17.0 NPM version: 8.15.0 npm ERR! C:\xxx\GIT\NewTestProject\node_modules\esbuild\install.js:93 npm ERR! thr ...

Integrate Vue Login Functionality using Axios HTTP Requests

Hello everyone! I am new to Vue and currently struggling with making an HTTP Request to my backend. When I check the browser console, I can see the access token retrieved from /login endpoint but when I try to fetch data from api/users, it returns "Token ...