Получение данных из нескольких дочерних компонентов Vue js - PullRequest
0 голосов
/ 13 октября 2019

Я несколько дней ломаю голову, пытаясь понять, как получить данные от дочерних компонентов.

Ситуация такая.

У меня есть один родительский компонент с именем Post, в котором пользователь может выбрать дату, заголовок, описание и который может содержать несколько экземпляров Event компонентов. Event компонент содержит поля, такие как заголовок, описание, посетители.

Пользователь должен иметь возможность добавлять несколько Event компонентов, что означает, что у меня есть несколько компонентов Event в компоненте Post.

Итак, я не могу понять, как я могусоздайте мои компоненты так, чтобы внутри моего Post компонента был массив Event объектов, которые я позже смогу отправить в мой API.

структура нужного мне объекта post:

// Post.vue
{ 
    "date": '',
    "name": '',
    "description": '',
    "events": {
       {
        "title": '',
        "description": '',
        "attendees": ''
       },
       {
        "title": '',
        "description": '',
        "attendees": ''
       }
    }
}

Итак, я не знаю, как и как использовать для этого vuex. Я пытался использовать $ emit для передачи данных, но не смог найти его подходящим для передачи данных в Post модель.

Может кто-нибудь указать мне, где мне искать это?

EDIT # 1 : добавлен пример кода

код для компонентов:

<template>
  <v-form>
    <v-container>
      <v-row>
        <v-col
          cols="12"
          md="4"
        >
          <v-date-picker v-model="post.date" scrollable>
            <v-spacer />
            <v-btn text color="primary" @click="modal = false">
              Cancel
            </v-btn>
            <v-btn text color="primary" @click="$refs.dialog.save(date)">
              OK
            </v-btn>
          </v-date-picker>
        </v-col>

        <v-col
          cols="12"
          md="4"
        >
          <v-text-field
            v-model="post.name"
            label="name"
            required
          />
        </v-col>

        <v-col
          cols="12"
          md="4"
        >
          <v-textarea
            v-model="post.description"
            name="description"
            label="Description"
            dense
            value
            rows="4"
            hint
          />
        </v-col>
      </v-row>
      <v-row>
        <v-btn primary rounded @click="addLine">
          Add Event
        </v-btn>
        <v-expansion-panels accordion>
          <UserEvent
            v-for="(line, index) in lines"
            :key="index"
            @addLine="addLine"
            @removeLine="removeLine(index)"
          />
        </v-expansion-panels>
      </v-row>
    </v-container>
  </v-form>
</template>

<script>
import UserEvent from './partials/event'
export default {
  name: 'Post',
  components: { UserEvent },
  data () {
    return {
      post: [],
      lines: [],
      blockRemoval: true
    }
  },
  watch: {
    lines () {
      this.blockRemoval = this.lines.length <= 1
    }
  },
  mounted () {
  },
  methods: {
    addLine () {
      const checkEmptyLines = this.lines.filter(line => line.number === null)
      if (checkEmptyLines.length >= 1 && this.lines.length > 0) { return }
      this.lines.push({
        title: null,
        description: null,
        attendees: null
      })
    },
    removeLine (lineId) {
      if (!this.blockRemoval) { this.lines.splice(lineId, 1) }
    }
  }
}
</script>

и дочерний компонент UserEvent

// UserEvent.vue
<template>
  <v-expansion-panel>
    <v-expansion-panel-header>Event details</v-expansion-panel-header>
    <v-expansion-panel-content>
      <v-row>
        <v-col cols="12" md="6">
          <v-text-field
            v-model="event.title"
            label="Title"
            required
          />
        </v-col>

        <v-col
          cols="12"
          md="6"
        >
          <v-text-field
            v-model="event.atttendees"
            label="Atendees"
            required
          />
        </v-col>

        <v-col
          cols="12"
          md="12"
        >
          <v-textarea
            v-model="event.description"
            name="description"
            label="Description"
            dense
            value
            rows="4"
            hint
          />
        </v-col>
        <v-col
          cols="12"
          md="3"
        >
          <div class="block float-right">
            <v-btn @click="removeLine(index)" />
            <v-btn v-if="index + 1 === lines.length" @click="addLine" />
          </div>
        </v-col>
      </v-row>
    </v-expansion-panel-content>
  </v-expansion-panel>
</template>

<script>
export default {
  name: 'UserEvent',
  props: ['line', 'index'],
  data () {
    return {
      event: []
    }
  },
  methods: {
    addLine () {
      this.$emit('addLine')
    },
    removeLine (index) {
      this.$emit('removeLine', index)
    }
  }
}
</script>

1 Ответ

0 голосов
/ 14 октября 2019

Вот пример с аналогичной структурой, которая была задана в вопросе:

{
  name: String,
  events: [
    title: String,
    description: String,
  ],
}

Этот пример позволяет пользователю открыть форму, чтобы добавить новое событие. Когда эта форма отправляется, данные события добавляются в состояние родительского компонента.

Родитель

<template>
  <div>
    <input v-model="name" />
    <ul v-if="events.length">
      <li v-for="(event, index) in events" :key="index">
        <span>{{ event.title }}</span>
        <span>{{ event.description }}</span>
      </li>
    </ul>
    <Event v-if="isNewEventFormVisible" @submit="addEvent" />
    <button v-else @click="showNewEventForm">add event</button>
  </div>
</template>
import Event from '~/components/Event';

export default {
  components: { Event },
  data() {
    return {
      name: 'Example Post',
      events: [],
      isNewEventFormVisible: false,
    };
  },
  methods: {
    addEvent({ title, description }) {
      this.isNewEventFormVisible = false;
      this.events.push({ title, description });
      // TODO: call you API here to update
    },
    showNewEventForm() {
      this.isNewEventFormVisible = true;
    },
  },
};

Событие

<template>
  <form @submit.prevent="onSubmit">
    <input v-model.trim="title" type="text" />
    <br />
    <textarea v-model.trim="description" />
    <button type="submit">submit</button>
  </form>
</template>
export default {
  data() {
    return {
      title: '',
      description: '',
    };
  },
  methods: {
    onSubmit() {
      this.$emit('submit', {
        title: this.title,
        description: this.description,
      });
    },
  },
};

Вы можете представить более сложную версию этого, где события доступны для редактирования. В этом случае каждый Event может взять реквизиты и привязать их в качестве значений к своему входу вместо использования v-model s.

...