How to use Emit and computed/watch

Asked

Viewed 909 times

0

I am new to Vuejs and started to develop a project to study a spreadsheet launching hours and calculation of hours worked.

I am using in the Laravel 5.5 project with Vuejs 2 and Momentjs to calculate the differences.

But I couldn’t figure out how to use Emit to send out my son to the father the updated data and how to do the field Trabalhado be updated alone with the calculation of moment(moment(this.entrada_1,"hh:mm").diff(moment(this.saida_1,"hh:mm"))).format("hh:mm"); (initially just the first difference to be able to learn and then try to calculate the rest.

Tabela de Exemplo Above is the model of the table I am developing and below the Blade and json codes

// blade.php
<vue-appointment :timetable="{{ $timetable }}"></vue-appointment>
<!-- timetable é o objeto abaixo -->

// jsonObject
{
   days: [
     { numero: 1, nome: "QUI", entrada_1: "00:00:00", saida_1: "00:00:00", trabalhado: "00:00:00" //...},
     { numero: 2, nome: "SEX", entrada_1: "00:00:00", saida_1: "00:00:00", trabalhado: "00:00:00" //...}
     { numero: 3, nome: "SÁB", entrada_1: "00:00:00", saida_1: "00:00:00", trabalhado: "00:00:00" //...}
   ]
}

Below the example of my 2 Components Vuejs.

Apointment.

<template>
<div class="row">
    <div class="col-xs-12">
        <div class="table-responsive">
            <table class="table table-condensed table-striped">
                <thead>
                    <tr>
                        <th width="20px">#</th>
                        <th width="20px" class="text-center">Dia</th>
                        <th class="text-center">Entrada</th>
                        <th class="text-center">Saída</th>
                        <th class="text-center">Entrada</th>
                        <th class="text-center">Saída</th>
                        <th class="text-center">Entrada</th>
                        <th class="text-center">Saída</th>
                        <th class="text-center">Entrada</th>
                        <th class="text-center">Saída</th>
                        <th class="text-center">Trabalhado</th>
                    </tr>
                </thead>
                <tbody>
                    <vue-appointment-row v-for="day in timetable.days" :key="day.virtual_id" :day=day></vue-appointment-row>
                </tbody>
            </table>
        </div>
    </div>
</div>
</template>

<script>
import {TheMask} from 'vue-the-mask'
import { Moment } from 'moment'

export default {

    props: ['timetable', 'old'],

    components: { TheMask },

    data () {
        return {
            object: {}
        }
    },

    mounted() {
        console.log(this.timetable);
    },

    methods: {

    },

    computed: {
    }

}
</script>

Appointmentrow.See

<template>
<tr>
    <td>{{ day.numero }}</td>
    <td>{{ day.nome }}</td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_1]'" :masked="true" required v-model="day.entrada_1"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_1]'" :masked="true" required v-model="day.saida_1"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_2]'" :masked="true" required v-model="day.entrada_2"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_2]'" :masked="true" required v-model="day.saida_2"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_3]'" :masked="true" required v-model="day.entrada_3"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_3]'" :masked="true" required v-model="day.saida_3"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_4]'" :masked="true" required v-model="day.entrada_4"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_4]'" :masked="true" required v-model="day.saida_4"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][trabalhado]'" :masked="true" required v-model="day.trabalhado"></the-mask></td>
</tr>
</template>

<script>
import {TheMask} from 'vue-the-mask'
import { Moment } from 'moment'

export default {

    props: ['day'],

    components: { TheMask },

    data () {
        return {
            object: {}
        }
    },

    mounted() {
    },

    methods: {
    },

    computed: {}

}
</script>

An explanation of how to use computed/watch in this situation to update the work as you edit the line, would help me to better understand how this computed/watch process works.

1 answer

1

If I understand correctly, in this case in my opinion the best approach is using the Sync Modifier.

Basically, for you to transmit the value that is being typed in the component "child", in case the AppointmentRow.vue, for the "parent" component, Appointment.vue, you can simply put the suffix .sync in prop use day.

Then inside the component AppointmentRow.vue, you create a watch in this prop, where will issue the value being typed for the parent, follows below:

watch: {
  day (newValue) {
    this.$emit('update:day', newValue)
  }
}

For each change in value day, the watch will be executed. Each change in value can be received by parameter. In turn, the typed value of each attribute changed to the "parent component".

I made your example like this:

Appointment.

<template>
  <div class="row">
      <div class="col-xs-12">
          <div class="table-responsive">
              <table class="table table-condensed table-striped">
                  <thead>
                      <tr>
                          <th width="20px">#</th>
                          <th width="20px" class="text-center">Dia</th>
                          <th class="text-center">Entrada</th>
                          <th class="text-center">Saída</th>
                          <th class="text-center">Entrada</th>
                          <th class="text-center">Saída</th>
                          <th class="text-center">Entrada</th>
                          <th class="text-center">Saída</th>
                          <th class="text-center">Entrada</th>
                          <th class="text-center">Saída</th>
                          <th class="text-center">Trabalhado</th>
                      </tr>
                  </thead>
                  <tbody>
                    <tr v-for="day in days" :key="day.virtual_id">
                      <appointment-row :day.sync="day">                      
                      </appointment-row>
                      p {{ day }}
                    </tr>
                  </tbody>
              </table>
          </div>
      </div>
  </div>
</template>

<script>
  import AppointmentRow from './AppointmentRow'

  export default {
    props: ['timetable', 'old'],
    components: { AppointmentRow },
    data () {
      return {
        days: [
          { numero: 1, nome: 'QUI', entrada_1: '00:00:00', saida_1: '00:00:00', trabalhado: '00:00:00' },
          { numero: 2, nome: 'SEX', entrada_1: '00:00:00', saida_1: '00:00:00', trabalhado: '00:00:00' },
          { numero: 3, nome: 'SÁB', entrada_1: '00:00:00', saida_1: '00:00:00', trabalhado: '00:00:00' }
        ]
      }
    }
  }
</script>

Appointmentrow.See

<template>
  <div>
    <td>{{ day.numero }}</td>
    <td>{{ day.nome }}</td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_1]'" :masked="true" required v-model="day.entrada_1"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_1]'" :masked="true" required v-model="day.saida_1"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_2]'" :masked="true" required v-model="day.entrada_2"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_2]'" :masked="true" required v-model="day.saida_2"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_3]'" :masked="true" required v-model="day.entrada_3"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_3]'" :masked="true" required v-model="day.saida_3"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][entrada_4]'" :masked="true" required v-model="day.entrada_4"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][saida_4]'" :masked="true" required v-model="day.saida_4"></the-mask></td>
    <td class="text-center"><the-mask class="form-control" :mask="['##:##']" :name="'days['+day.numero+'][trabalhado]'" :masked="true" required v-model="day.trabalhado"></the-mask></td>
  </div>
</template>

<script>
  import { TheMask } from 'vue-the-mask'

  export default {
    props: ['day'],
    components: { TheMask },
    watch: {
      day (newValue) {
        this.$emit('update:day', newValue)
      }
    }
  }
</script>

In the paragraph p {{ day }} can be verified the change of the value, each time it is being typed inside the child component.

Another way to accomplish this, without using the sync Modifier, is using a v-model instead of prop day:

<appointment-row v-model="day"></appointment-row>

Within the AppointmentRow.vue you perform the exchange of day for value throughout the code:

props: ['value'],

And change the $emit of watch:

this.$emit('input', newValue)

The operation will be the same, however if in the future you want to pass another prop, and the value of this prop should be transmitted to the father, there is no use with the v-model, only with the sync Modifier.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.