7

I have a needed to create a local variable in my Vue template to shorten references to an otherwise long object $v.form.text, as shown in the example below:

<input 
    :class="{ error: !$v.form.text.required }"
    v-model.trim="$v.form.text.$model" 
/>

I would like to be able to access the $v.form.text nested object in my template as simply text.

<input 
    :class="{ error: !text.required }"
    v-model.trim="text.$model" 
/>

There is usually a lot more code than in the example above, justifying creating a temporary variable, but the problem is the same as shown.

Note: I have already solved this, please see answer below, and simply want to document the solution for others who might be searching for the same.

Paul Bastowski
  • 1,166
  • 1
  • 8
  • 9

2 Answers2

7

I just had this same problem and thought of another hack/workaround... Note I haven't tried this yet but should work.

Just use v-for with a single inline array containing your long expression, i.e.

<span v-for="item in [my.big.long.expression.item]">{{item.foo}} {{item.bar}}</span>

:)

LMK
  • 1,496
  • 1
  • 13
  • 15
  • This was the first thing I thought of but I was hoping there would be something better that was built in. Like `v-var` or something that I somehow overlooked. – ADJenks Sep 05 '20 at 00:50
6

I could of course just use a computed function to do this, but in some cases it is not possible, such as when you're inside a v-for and want your computed to refer to the loop's iterator variable. In such cases, my solution is as follows:

<div :set="text=$v.form.text">
    <input 
        :class="{ error: !text.required }"
        v-model.trim="text.$model" 
    />
</div>

For those that may now be thinking, "Hey, I didn't know there was an undocumented :set in Vue", there isn't.

What I'm doing here is relying on the fact that Vue will evaluate the JavaScript of any bound attributes and I just chose to invent an unused attribute called :set.

As a reminder, a bound attribute is one that is prefixed with a : or v-bind:. The JavaScript expression inside the double quotes will be evaluated in the context of the current component and the item variable will still be available outside of the v-for in which it is being set. So, it's not a local variable, as such, rather, it's a locally assigned, component scope variable.

Make sure to add this variable to your variable declarations in the data hook.

data() { return { 
    text: '' 
}}

Here is a link to a CodePen showing this pattern at work https://codepen.io/pbastowski/pen/PXqjPG?editors=1100

Paul Bastowski
  • 1,166
  • 1
  • 8
  • 9
  • In case this pattern is used inside a `v-for` AND that some event handlers (e.g. `@click`) use the variable, the solution from LMK is necessary. – Rémi May 07 '20 at 22:08