Accessing computed properties from template dynamically

I have a simple component that looks like this:

<template>
  <child-component :prop="getComputed(dynamicValue)">
</template>

<script>
export default {
  data() {
    dynamicValue: 'computedPropOne'
  },
  computed: {
    one: {
      // large loop
    },
    two: {
      // large loop
    }
  },
  methods: {
    getComputed (property) {
      return this[property]
    }
  }
}
</script>

My constraints are the following:

  1. dynamicValue changes between 'one' and 'two' (there are more values, I’m simplifying) on the fly and depending on that, I would like to pass the matching computed property to the ChildComponent.
  2. Because you can’t use this in the template, I can’t do :prop="this[dynamicValue]"
  3. I could bundle both computed properties in a single one and do :prop="singleComputedPropWIthBoth[dynamicValue]" but I don’t want them both recalculated every time one of them changes.

Therefore I’m using the getComputed method to achieve the desired effect. But it feels a bit ugly, is there a better solution?

I can’t do :prop=“this[dynamicValue]”

:prop="$data[dynamicValue]"

should work - check https://vuejs.org/v2/api/#vm-data

Maybe there is a fancier way… this is has been the most reliable and straightforward approach for me…

<template>
  <child-component :prop="myComputedValue">
</template>

<script>
export default {
  data() {
    dynamicValue: 'computedPropOne'
  },
  computed: {
    myComputedValue : function () {
       return this.doCompute(this.dynamicValue);
    },
    one: {
      // large loop
    },
    two: {
      // large loop
    }
  },
  methods: {
    doCompute (property) {
      return this[property]
    }
  }
}
</script>
1 Like

@sqal nope, this.$data only has static properties defined in data, without the computed ones which I need.
@rowanxmas sorry, but that’s the same thing I have now, just with this.doCompute(this.dynamicValue) extracted to a computed property instead of being directly in the template as doCompute(dynamicValue).

@mzgajner I guess I don’t understand the problem … do you have a functional JSFiddle or something that highlights the issue?

I’m sure what you’re looking for has a solution, but I think your example is missing something that key that’s make it not click for me :slight_smile:

It’s not really a problem, my current code works, it’s just that it seems a bit hacky to have that getComputed method and I was asking about possible ways to do it more cleanly.

If you take a look at this fiddle, It would be nice if I could say something like this[listName] for direct access in the template instead of going through getComputedList(listName), but at the end of the day it’s not that big of a deal.

If dynamiValue is part of your components data, it should be easy to create another composites prop that returns the right computed prop’s value depending on that?

https://jsfiddle.net/yMv7y/2170/

If you do something more like this, then instead of doing a computed value you could do a set on the data directly and/or get it from a Vuex store.

Use _self[dynamicValue] instead of this[dynamicValue] in the binding.

2 Likes

Works for me.

But the “_self” variable is reserved for Vue’s internal properties (see #2098). In other words, this implementation can breaking in the future.

I prefer this way:

<template>
  <input v-model="mySelf[dynamicValue]">
</template>

<script>
export default {
  data() {
    return {
      mySelf: this
    }
  }
}
</script>

For more details see: https://stackoverflow.com/questions/52104176/use-of-self-attribute-from-vue-vm-is-reliable