Reputation: 147
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>
Upvotes: 1
Views: 1364
Reputation: 147
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.
Upvotes: 0
Reputation: 43881
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>
Upvotes: 0
Reputation: 25312
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)
}
}
Upvotes: 1