2

I've read answers such as this, but I can't get my template to compile.

I need to concatenate a string with a variable in v-model to bind to an array inside an object:

<li v-for="name in names">
    <input type="checkbox" v-model="'checked.'+name">
    ....

I just get a compile error though.

Also when I do this:

:data-test="'checked.'+name"

It compiles fine, so it's something with v-model.

The compile error is:

Syntax Error: SyntaxError: Unexpected token (1:1161)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
panthro
  • 22,779
  • 66
  • 183
  • 324

3 Answers3

3

Just in case a slightly different perspective helps: Whether you use it in a v-model or :data-test directive

'checked.'+name

results in a string. Although it probably isn't what one would normally want to do, that is syntactically legal for an arbitrary v-bind (e.g. :data-test). That is not, however, syntactically legal for a v-model. As other have pointed out, v-model attempts to assign a value on "change" events. It would be equivalent, for example, to

'checked.foo' = true;

when what I think you want is

checked.foo = true;

It's hard to say for sure without seeing more of your code, but it may be the case that

<input type="checkbox" v-model="checked[name]">

is sufficient for you.

Stephen Thomas
  • 13,843
  • 2
  • 32
  • 53
1

The v-model="name" helps you do two things.

  1. :value="name"
  2. @input="name = $event

However, in your case, you're doing v-model="'checked.'+name", which means:

  1. :value="'checked.'+name" // Which is perfectly fine
  2. @input="'checked.'+name = $event" // This would cause an error.

Documentation can be found here.

Below is some solution of mine: JsFiddle

  computed: {
    checkedName: {
      // getter
      get: function () {
        return `${this.prefix}${this.name}`;
      },
      // setter
      set: function (newValue) {
        this.name = newValue.replace(this.prefix, '');
      }
    }
  },

then

<input type="checkbox" v-model="checkedName">
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Cloud Soh Jun Fu
  • 1,456
  • 9
  • 12
  • This does not work. Compile error `SyntaxError: Assigning to rvalue` – panthro Apr 02 '19 at 16:23
  • Thanks for updating your answer, but I'm afraid the binding still does not work. `return checked.${this.name}`;` how does it know the name if nothiing is passed to the setter `set: function (newValue)` from `v-model="checkedName"`? – panthro Apr 02 '19 at 16:28
  • `set:` is triggered when you do `checkedName = $event`, the `newValue` is `$event`. Check the [jsfiddle](https://jsfiddle.net/qxtuezmj/) – Cloud Soh Jun Fu Apr 02 '19 at 16:34
  • Example not correct as it's not in a loop or even a checkbox. – panthro Apr 02 '19 at 16:38
  • I have updated the [fiddle](https://jsfiddle.net/qxtuezmj/2/), but I'm not sure what are you trying to achieve. What value you want to store in the `names`? – Cloud Soh Jun Fu Apr 02 '19 at 16:54
  • Why are you putting string into value of a checkbox? Shouldn't it be `boolean`? Do you have a `object` called `checked` and you want to access its attribute using `name`? if `names[0] = 'asd'`, you want to access `checked.asd`? – Cloud Soh Jun Fu Apr 02 '19 at 17:00
0

You can't do that.

v-model is used for two-way data binding and is a syntactic sugar for :checked="myField" + @change="evt => myField = evt.target.checked in the case of a checkbox.

As you can see, myField must be a valid left-hand side expression in JS, this is by the way one of the rules precised by Vue to have a valid v-model:

The directive does not have the attribute value which is valid as LHS. E.g. <input v-model="foo() + bar()">

And that is exactly why your template doesn't compile. Vue can understand how to bind the data in one way because it can assign 'checked.'+name to a variable, but it can't assign a variable to 'checked.'+name - that is not a valid left-hand sign expression.

Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
  • But when I manually set the v-model to do what I want, it works fine. I'm just trying to concat a string and var name. – panthro Apr 02 '19 at 16:11
  • That's exactly what I say. Vue can concat easily. It cannot deconcat. One way of the required two-way databinding is not possible. – Nino Filiu Apr 02 '19 at 16:13
  • Im not sure I understand what you are saying. `v-model="checked.myname"` works, so why cant we just concat this value from a var? – panthro Apr 02 '19 at 16:14
  • we can *concat* we can't do the reverse. By two-way-binding to `'checked.'myname`, Vue won't be able to know which variable to update when the input value gets updated because the object reference is lost during the concatenation. Thus the error. – Nino Filiu Apr 02 '19 at 16:20
  • The object reference will not be lost during the concatenation, the concatenation creates the reference. For example, the concatenation produces `v-model="checked.myname"` which references an item in data. – panthro Apr 02 '19 at 16:24
  • Apologies, I was wrong on the object reference losing. I answered too hastily. I edited my answer so as to include an update with better explanation and a link to the docs explaining why your template won't compile. Is that better now? – Nino Filiu Apr 02 '19 at 17:12