Skip to content Skip to sidebar Skip to footer

Pass Properties From Parent Component To All Transcluded Children Component In Vue

I would like to pass some properties from a parent to all of his children when those are transcluded (content distribution syntax). In this case, the parent doesen't know (as far a

Solution 1:

Props allow data flow only one level. If you want to perpetuate data, you can use an event bus instead.

Instantiate an event bus with an empty Vue instance in your main file.

var bus = new Vue();

Then in your parent, emit the event with data to be passed

 bus.$emit('myEvent', dataToBePassed);

Listen for myEventanywhere you want to pick up the data. In your case, it is done in your child components

bus.$on('myEvent', function(data) {
     .....
});

Solution 2:

At this point (I'm not a vue expert) I just could think in this solution.

Assign every component's props is boring I agree, so why not doing it programmatically?

// Create a global mixin
Vue.mixin({
  mounted() { // each component will execute this function after mountedif (!this.$children) {
      return;
    }

    for (const child of this.$children) { // iterate each child componentif (child.$options._propKeys) {
        for (const propKey of child.$options._propKeys) { // iterate each child's props// if current component has a property named equal to child prop keyif (Object.prototype.hasOwnProperty.call(this, propKey)) {
            // update child prop valuethis.$set(child, propKey, this[propKey]);

            // create a watch to update value again every time that parent property changesthis.$watch(propKey, (newValue) => {
              this.$set(child, propKey, newValue);
            });
          }
        }
      }
    }
  },
});

This works but you will get an ugly vue warn message:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.

I'm not sure if this is a good solution but it works, so if you decide to use just keep in mind Global-Mixin recomendations:

Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components.

Please see a full example at https://github.com/aldoromo88/PropsConvention

Hope it helps

Solution 3:

Here is my solution, that's probably not a great deal, but that's the cleanest solution for what I want to do right now. The principle is to create computed properties that will use own component prop if they exist, or get $parent values otherwise. The real prop would then be accessible in this._prop.

Vue.component('my-children', {
    props: ["prop1", "prop2"],
    template: "<div>{{_prop1}} - {{_prop2}}</div>",
    computed: {
        _prop1: function() {
            returnthis.prop1 || this.$parent.prop1;
        },
        _prop2: function() {
            returnthis.prop2 || this.$parent.prop2;
        }
    }
});

Here is a mixin generator that does that in a more elegant way, and with, possibly, multiple levels :

functionpassDown(...passDownProperties) {
    const computed = {};
    passDownProperties.forEach((prop) => {
        computed["_" + prop] = function() {
            returnthis[prop] || this.$parent[prop] || this.$parent["_" + prop];
        };
    });
    return { computed };
}

Vue.component('my-children', {
    props: ["prop1", "prop2"],
    template: "<div>{{_prop1}} - {{_prop2}}</div>",
    mixins: [passDown("prop1", "prop2")]
});

Post a Comment for "Pass Properties From Parent Component To All Transcluded Children Component In Vue"