Vue: Provide/Inject in functional components

Created on 14 Mar 2017  路  5Comments  路  Source: vuejs/vue

I understand that functional components are instanceless, but given that they still have access to the parent context, wouldn't it make sense to also give them access to provided ancestor properties?

For example, I created vue-mobiledoc-editor. In the current version, I used a shared Vue instance that I passed to the editor and button components so that they could communicate with each other; and since there were various types of buttons (e.g. section, markup, and link buttons), I made the component functional.

I want to upgrade the code to using provide/inject since not having to pass the shared instance to every component makes the code more maintainable and will also make it easier to create multiple editor instances. However, it is not possible to inject exposed ancestor data and methods in functional components. If there is no specific reason for this, I'd like to make this a feature request.

feature request

Most helpful comment

Hi Evan,

I think there is a problem with Vue 2.6.6 and provide/inject.

Lets say that we have one <page> not functional component that provides its prop "mode".

{
    name: 'page',
    provide() {
        return {
            pageMode: this.mode
        }
    },
    props: {
        mode: {
            type: String
        },

Also we have one <field> functional component:

{
    name: 'field',
    functional: true,
    inject: ['pageMode']
}

Working: When <field> is used as nested component

My page component:

<page>
    <other-component> --> it calls <field> inside

Broken: When <field> is used directly on the page under <page>

My page component:

<page>
    <field>

I got:

vue.js?b2d9:634 [Vue warn]: Injection "pageMode" not found

Andrey

All 5 comments

This has been implemented in #5204, will be merged when we release 2.3.

@yyx990803
Whether we can use the selector or x-path to inject dependencies.
In a component tree, like A>B>C>D. (A, B, C, D is $options.name)
We define provider in A. like: A.provider = { 'A>B>C>D': obj }.
All descendants in A will search A.provider, D will be find the obj.
The obj can contain events, default data, etc.
According to this idea, I wrote some code in my github. Looking forward to your suggestion.

@Kingwl @yyx990803 Are you sure this is working now? Finally got around to using this in my component, but ctx.injections does not have any properties.

The button component is nested under the editor component and so it should be receiving the provided properties. I can even verify the props in the editor component (this._provided). Yet they're not showing up in the functional component context.

@alidcastano if it's not working, please open a dedicated issue with proper reproduction.

Hi Evan,

I think there is a problem with Vue 2.6.6 and provide/inject.

Lets say that we have one <page> not functional component that provides its prop "mode".

{
    name: 'page',
    provide() {
        return {
            pageMode: this.mode
        }
    },
    props: {
        mode: {
            type: String
        },

Also we have one <field> functional component:

{
    name: 'field',
    functional: true,
    inject: ['pageMode']
}

Working: When <field> is used as nested component

My page component:

<page>
    <other-component> --> it calls <field> inside

Broken: When <field> is used directly on the page under <page>

My page component:

<page>
    <field>

I got:

vue.js?b2d9:634 [Vue warn]: Injection "pageMode" not found

Andrey

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aviggngyv picture aviggngyv  路  3Comments

bdedardel picture bdedardel  路  3Comments

Jokcy picture Jokcy  路  3Comments

julianxhokaxhiu picture julianxhokaxhiu  路  3Comments

6pm picture 6pm  路  3Comments