1

I have a scenario where an expression I wish to execute is dynamically loaded into a component. I am unable to set the expression into v-if as it is a literal string, not the actual binding expression.

I had a look at using vm.$watch however the expressions are only allowed to be dot notation paths, rather than single javascript expressions.

vm.$watch usage: Watch an expression or a computed function on the Vue instance for changes. The callback gets called with the new value and the old value. The expression only accepts simple dot-delimited paths. For more complex expression, use a function instead.

Is there some part of vuejs that I can use to achieve this? I assume that the binding expressions for the v-if directive etc are ultimately strings that are being parsed and evaluated in a given context, it just just whether these functions are available for use in components?

Hopefully this example below shows a more complete picture of what I am trying to achieve:

<template>
    <div>
        <div v-if="expression"></div>
    </div>
</template>

<script>
  export default {
    name: 'mycomponent'
    data: function() {
      var1: 5,
      var2: 7,
      expression: null
    },
    created: function() {
      this.$http.get('...').then((response) => {
        // Sample response:
        // {
        //   'expression' : 'var1 > var2'
        // }
        // TODO: Not this!!
        this.expression= response.expression;
      });
    }
  }
</script>

3 Answers 3

1

You could create a method for this, e.g. :

<div v-if="testExpression"></div>

And add methods in your component config :

methods: {
    testExpression() {
        return eval(this.expression)
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the suggestion. I am trying (as mentioned by @roy-j below) to avoid using eval as it is quote: Not Generally Good JavaScript. For the time being I have decided to use link which provides a degree of safety (albeit not bullet proof, I think probably an improvement over eval).
0

Be aware that evaluating expressions requires you to use things that are Not Generally Good JavaScript, such as eval and with. Take care to ensure that you control what can get in to any use of eval.

I recommend using a computed rather than a method for this; it seems more well-suited (and avoids requiring invocation parentheses).

new Vue({
  el: '#app',
  data: {
    var1: 5,
    var2: 7,
    expression: null
  },
  computed: {
    evaluatedExpression: function() {
      with(this) {
        try {
          return eval(expression);
        } catch (e) {
          console.warn('Eval', expression, e);
        }
      }
    }
  },
  created: function() {
    setTimeout(() => {
      this.expression = 'var1 < var2';
    }, 800);
    setTimeout(() => {
      this.expression = 'var1 > var2';
    }, 2500);
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<div id="app">
  {{expression}}, {{evaluatedExpression}}
  <div v-if="evaluatedExpression">
    Yep
  </div>
  <div v-else>
    Nope
  </div>
</div>

1 Comment

Many thanks for the example. As commented on @soju's post, i am trying to avoid using eval to achieve this, so for the time being am using link.
0

Tidying up a question I have left open for over a year, the answer I have ended up using is to use the Angular Expression library Angular Expressions for my purposes, but will likely be moving to using the Friendly Enough Expression Language library in future as both my client and server will evaluate similar expressions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.