ledlogic
ledlogic

Reputation: 850

How to bind to array objects in vue?

I have a data array that I want to bind input element entry (integers) into data fields, and then total them. This is akin to a spreadsheet where it can compute the sum or difference of different values specified in the same column.

I don't understand from vue.js documentation, what it takes to make two-way data binding work on these array objects. I can't tell if the values are updating in the array. Either they aren't updating the array, or the summation link is not being updated. Do you have a recommendation for determining if the data binding is broken, or why the expression is not getting updated?

<tr v-for="(row, powerIndex) in powers">
    <td :class="powerlabelclass(row)">{{ row.name }}</td>
    <td class="power-item" v-for="turn in turns">
        <div v-if="row.expression">
            <input :class="poweritemclass(row)" type="number" :tabindex="tabindex(powerIndex, turn)" :value="calculatepower(powerIndex, turn)" />       
        </div>
        <div v-else>
            <input :class="poweritemclass(row)" type="number" :tabindex="tabindex(powerIndex, turn)" :value="row.turns[turn]" />        
        </div>
    </td>
</tr>

Here is the js fiddle: https://jsfiddle.net/ledlogic/fst561by/

Upvotes: 2

Views: 7414

Answers (2)

Barr J
Barr J

Reputation: 10919

Fisrt of all - you are missing v-model which is necessary for two way binding.

I suggest you try and understand the concept of v-model first:

You can use the v-model directive to create two-way data bindings on form input, textarea, and select elements.

Please note that:

-

v-model will ignore the initial value, checked or selected attributes found on any form elements. It will always treat the Vue instance
data as the source of truth. You should declare the initial value on
the JavaScript side, inside the data option of your component.

  • For languages that require an IME (Chinese, Japanese, Korean etc.), you’ll notice that v-model doesn’t get updated during IME composition. If you want to cater for these updates as well, use input event instead.

Now for your example:

What it should look like is:

<tr v-for="(row, powerIndex) in powers">
    <td :class="powerlabelclass(row)">{{ row.name }}</td>
    <td class="power-item" v-for="turn in turns">
        <div v-if="row.expression">
            <input :class="poweritemclass(row)" type="number" :tabindex="tabindex(powerIndex, turn)" v-model="calculatepower(powerIndex, turn)" />       
        </div>
        <div v-else>
            <input :class="poweritemclass(row)" type="number" :tabindex="tabindex(powerIndex, turn)" v-model="row.turns[turn]" />        
        </div>
    </td>
</tr>

I'd suggest you to look at this post for better context.

Upvotes: 1

ittus
ittus

Reputation: 22393

You need to use v-model instead of :value for 2 way binding

I assume you want to calculate total value automatically. You only need to change:

  <div v-else>
     <input :class="poweritemclass(row)" type="number" :tabindex="tabindex(powerIndex, turn)" v-model="row.turns[turn]" />        
  </div>

Demo https://jsfiddle.net/ittus/1z6qu43y/

Upvotes: 2

Related Questions