Zhanna_K
@Zhanna_K
in progress

Можно ли получить данные из дочернего компонента?

Делаю большую форму, вынесла элементы группы радиокнопок и чекбокса в отдельные компоненты с расчетом на то, что это сделает код более лаконичным.
Как теперь при кликах на них, получить данные в App, где собственно и хранятся все данные формы?
И вообще, возможно ли это или лучше все элементы формы держать в одном темплэйте?
Вот структура проекта:

  • 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 (Фрагмент)
<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>
  • Вопрос задан
  • 196 просмотров
Решения вопроса 1
Kozack
@Kozack Куратор тега Vue.js
Thinking about a11y
ну, вот как то так и получать
<CustomRadio v-model="sex" />

Дочерние компоненты принимают дефолтное значение, и по клику стреляют событием с новым значением, которое уже принимает и сохраняет родитель.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
IgorPI
@IgorPI
Привожу пример рабочего компонента.
Обратите внимание на

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>
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы