How to use emit and computed / watch

0

I'm new to VueJS and started to develop a project to study a time release and time worked spreadsheet.

I'm using the Laravel 5.5 project with Vuejs 2 and MomentJS to calculate the differences.

But I could not figure out how to use the emit to send out the child data to the parent the updated data and how to make the Trabalhado field be updated alone with the moment(moment(this.entrada_1,"hh:mm").diff(moment(this.saida_1,"hh:mm"))).format("hh:mm"); calculation (initially only the first difference to be able to learn and then try to calculate the rest.

AboveisthetabletemplateIamdevelopingandbelowthebladesandjson

//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 is the example of my 2 VueJS components.

Apointment.vue

<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.vue

<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 better understand how this computed / watch process works.

    
asked by anonymous 22.02.2018 / 03:19

1 answer

1

If I understood correctly, in this case in my opinion the best approach is to use sync Modifier .

Basically, for you to pass the value being typed in the child component, in this case AppointmentRow.vue , to the parent component, Appointment.vue , you can simply put the .sync suffix in usa prop day .

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

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

At every change of the value day , watch will be executed. Each value change can be received per parameter. In turn, the typed value of each changed attribute for the "parent" component is being issued.

I've done your example like this:

Appointment.vue

<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.vue

<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 paragraph p {{ day }} you can check the value change every time you are typing inside the child component.

Another way to do this, without using sync Modifier , is to use v-model instead of day :

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

Inside the AppointmentRow.vue you perform the change from day to value in the whole 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 passed to the parent, there is no way to use it with v-model , only with sync Modifier .

    
22.02.2018 / 04:28