Dynamic input with the v-model directive in vue.js

1

I have a query v-for which brings me matches of n day. For each game I have two input where the user will mark the result, I need the v-model of said input to be dynamic.

HTML

<template>
  <div class="container">
    <div class="content">
      <form @submit.prevent="validateBeforeSubmit">
        <table class="table">
          <thead>
            <tr>
              <th><abbr title="Position">Local</abbr></th>
              <th><abbr title="Played">Pronostico</abbr></th>
              <th><abbr title="Played">-</abbr></th>
              <th><abbr title="Won">Pronostico</abbr></th>
              <th><abbr title="Drawn">Visitante</abbr></th>
            </tr>
          </thead>

          <tbody>

            <tr v-for="match in matchdays">
              <th>
                <figure class="image is-32x32">
                  <img :src="'/img/shield/'+match.teamlocal.shield">
                </figure>
                {{ match.teamlocal.name }}
              </th>
              <th>
                <div class="field has-addons">
                  <p class="control">
                    <input class="input" v-model.number="local"
                           type="number" placeholder="0">
                  </p>
                </div>
              </th>
              <th> - </th>
              <th>
                <div class="field has-addons">
                  <p class="control">
                    <input class="input" v-model.number="visitante" 
                           type="number" placeholder="0">
                  </p>
                </div>
              </th>
              <th>
                <figure class="image is-32x32">
                  <img :src="'/img/shield/'+match.teamvisitante.shield">
                </figure>
                {{ match.teamvisitante.name }}
              </th>
            </tr>
            <tr>
              <td colspan="5" class="tdcolspan5">
                <div class="block">
                  <button class="button is-success" type="submit">
                    <span class="icon is-small">
                      <i class="fa fa-check"></i>
                    </span>
                    <span>Save</span>
                  </button>
                  <!--<a class="button is-success">
                  <span class="icon is-small">
                  <i class="fa fa-check"></i>
                </span>
                <span>Save</span>
              </a>-->
            </div>
          </td>
        </tr>

      </tbody>
    </table>
  </form>

  {{ $data }}
</div>
</div>
</template>

javascript

<script>
export default {

  data () {
    return {
      matchdays: [],
      local: 0,
      visitante: 0
    }
  },

  created () {
    this.getMatches()
  },

  methods: {
    getMatches () {
      axios.get('/api/v1/matchday/'+this.$route.params.matchday )
      .then(response => {
        this.matchdays = response.data.matchdays.matches
      })
    },

    validateBeforeSubmit() {
      this.$validator.validateAll().then(() => {
        console.log("ok")
      }).catch(() => {
        console.log('fallo');
        // eslint-disable-next-line
        //alert('Correct them errors!');
      });
    }

  }
}
</script>
    
asked by Gerardo Argueta 03.04.2017 в 19:33
source

1 answer

2

Like any framework, Vue.js has things that have not yet been implemented and you must have the ingenuity to solve them. For your case, it occurs to me to populate the object that stores the scores initializing local and visitor to null. You must do this on hook created , before the component is mounted.

created () {
  this.matches.forEach(match => {
    this.scores[match] = {
      local: null,
      visitor: null
    }
  })
}

If to this, you add a form that wraps the inputs you could add the attribute required , since, since the scores have been initialized from% to null, Vue.js will not associate any value to the label.

Example

const app = new Vue({
  data: () => ({
    matches: [{
        key: 'avcn2r',
        local: 'Barcelona',
        visitor: 'Sp Gijón'
      },
      {
        key: 'clm7rv',
        local: 'Real Madrid',
        visitor: 'Las Palmas'
      },
      {
        key: '2kd034',
        local: 'Liverpool',
        visitor: 'Arsenal'
      },
      {
        key: 'pmkd29',
        local: 'Juventus',
        visitor: 'Sampdoria'
      }
    ],
    scores: {}
  }),
  methods: {
    showScores() {
      console.log(this.scores)
    }
  },
  created() {
    this.matches.forEach(match => {
      this.scores[match.key] = {
        local: match.local,
        visitor: match.visitor,
        scores: [null, null]
      }
    })
  }
})

app.$mount('#app')
button {
  background-color: #009BFF;
  border: 1px solid #009BFF;
  border-radius: 2px;
  color: #fff;
  font-family: 'Noto Sans';
  font-size: 14px;
  height: 35px;
  padding: 0 12px;
}

table {
  border-collapse: collapse;
  margin-top: 20px;
  width: 100%;
}

table thead {
  border-bottom: 3px solid #eee;
}

table th,
table td {
  color: #555;
  font-family: 'Noto Sans';
  font-size: 14px;
  padding: 15px;
  text-align: center;
}

table tbody tr:nth-child(odd) {
  background-color: #f9f9f9;
}

table tr:not(:last-of-type) {
  border-bottom: 1px solid #eee;
}

table td:not(:last-of-type) {
  border-right: 1px solid #eee;
}

table input {
  border: 1px solid #ccc;
  border-radius: 2px;
  color: #555;
  font-family: 'Noto Sans';
  font-size: 14px;
  padding: 5px 10px;
  width: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>

<div id="app">
  <button @click="showScores">Show scores</button>
  <table>
    <thead>
      <tr>
        <th>Local</th>
        <th>Visitante</th>
        <th>Resultado</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="match in matches">
        <td>{{ match.local }}</td>
        <td>{{ match.visitor }}</td>
        <td>
          <input v-model.number="scores[match.key].scores[0]" type="number" min="0" />
          <input v-model.number="scores[match.key].scores[1]" type="number" min="0" />
        </td>
      </tr>
    </tbody>
  </table>
</div>

Note that I have used random keys here, but you can use the concatenation of both computers as a key, for example, it is a matter of your preference or the API you use.

    
answered by 03.04.2017 в 20:53