Z
Z
Zhanna_K2020-10-26 13:39:24
Vue.js
Zhanna_K, 2020-10-26 13:39:24

Is it possible to get data from a child component?

I am making a large form, moved the elements of the group of radio buttons and the checkbox into separate components, with the expectation that this will make the code more concise.
How now, when clicking on them, get the data in the App, where all the form data is actually stored?
And in general, is it possible or is it better to keep all form elements in one template?
Here is the project structure:

  • app.vue
  • Components/
    • CustomRadioGroup.vue
    • ToggleBtn.vue



ToggleBtn
<template>
<label class="slider-container" style="width:40px, height:20px">
    <input type="checkbox" name="unsubscribe" value="true" />
    <span class="round"></span>
</label>
</template>


CustomRadioGroup
<template>
<div>
    <span class="group">
        <label class="container">
            <input id="male" name="sex" type="radio" value="муж" /><span class="checkmark"></span></label>

        <label for="male" class="title">Мужчина</label></span>

    <span class="group">
        <label class="container">
            <input id="female" name="sex" type="radio" value="жен" /><span class="checkmark"></span></label>
        <label for="female" class="title">Женщина</label>
    </span>
</div>
</template>

app.vue(Fragment)
<input id="phone_number" name="phone_number" type="text" placeholder="+7(965)-667-88-77" v-model.trim="phone_number" />
            <label for="phone_number">Телефон</label>
            <div class="radioBox">
                <!-- <CustomRadio v-model="sex" />   --> кастомная радиогруппа
            </div>
            <select class="clientGroup">
                <option>VIP</option>
                <option>Проблемные</option>
                <option>ОМС</option>
            </select>
            <span class="clientGroup_tip">Группа клиентов</span>
            <select class="clientDoctor">
                <option>Захаров</option>
                <option>Чернышева</option>
                <option>Иванов</option>
            </select>
            <span class="clientDoctor_tip">Лечащий врач</span>
            <div class="checkBox">
                <!-- <ToggleButton /> -->  кастомный чекбокс
                <span>Не отправлять СМС</span>
            </div>

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alex, 2020-10-26
@Zhanna_K

well, that's how it is to receive
<CustomRadio v-model="sex" />
Child components take a default value, and on click they fire an event with a new value, which the parent already accepts and saves.

I
Igor, 2020-10-26
@IgorPI

I give an example of a working component.
pay attention to

model: {
    prop: 'selected',
    event: 'change'
  },

<template>
  <v-autocomplete
    v-model="selected"
    :items="users"
    :search-input.sync="usersSearchQuery"
    persistent-hint
    :label="label"
    :rules="rules"
    :loading="loading"
  >
    <template
      v-slot:prepend
      v-if="visibleIcon && ['lg', 'md'].includes($vuetify.breakpoint.name)"
    >
      <v-icon class="pl-5 pr-9">mdi-account-tie</v-icon>
    </template>
    <template v-slot:selection="{ attr, on, item }">
      <span>{{ item.first_name }} {{ item.last_name }}</span>
    </template>
    <template v-slot:item="{ item }">
      <v-list-item-avatar
        color="indigo"
        class="headline font-weight-light white--text"
      >
        {{ item.first_name.charAt(0) }}
      </v-list-item-avatar>
      <v-list-item-content>
        <v-list-item-title>{{ item.first_name }} {{ item.last_name }}</v-list-item-title>
        <v-list-item-subtitle
          v-if="item.role"
          v-text="item.role.name"
        ></v-list-item-subtitle>
      </v-list-item-content>
    </template>
  </v-autocomplete>
</template>

<script lang="ts">
import Vue from 'vue'
import { debounce } from 'vuetify/src/util/helpers'
import { Users } from '@/api/Users'

export default Vue.extend({
  name: 'UserAutocomplete',
  model: {
    prop: 'selected',
    event: 'change'
  },
  props: {
    selectedId: {
      type: Number,
      default: 0
    },
    search: {
      type: String,
      default: ''
    },
    rules: {
      type: Array,
      default: undefined
    },
    visibleIcon: {
      type: Boolean,
      default: false
    },
    label: {
      type: String,
      default: ''
    }
  },

  data () {
    return {
      loading: false,
      selectOnce: false,
      selected: null,
      usersSearchQuery: null,
      usersProcessLoading: false,
      usersSearchDebounce: debounce((q: string) => {
        this.loading = true
        new Users().findUsers(q)
          .then(({ count, items }) => {
            this.users = items

            if (this.selectOnce === false) {
              this.selectOnce = true
              this.selected = this.users.find((e) => e.id === this.selectedId)
              console.log(this.selectedId, this.users)
              console.log(this.selected)
            }
          }).finally(() => {
            this.loading = false
          })
      }, 400),
      users: []
    }
  },

  watch: {
    selected (value) {
      this.$emit('change', value)
    },

    usersSearchQuery (val: string) {
      this.usersSearchDebounce(val)
    }
  },

  created () {
    this.usersSearchQuery = this.search
  }
})
</script>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question