@Esm322

Как получить свойство из props drilling по открытию модального окна?

Как получить id клиента из дочернего компонента по открытию модального окна ModalWindowChanges?
В родительском компоненте MainPage есть метод для открытия модального окна showModalChanges. Мне нужно, чтобы по открытию модального окна также передавался id выбранного клиента. Пытался через emit передать по цепочке вложенных компонентов, но ничего не вышло.

MainPage
<ClientTableTbody
          v-model:clients="clients"
          v-model:client-id="clientId"
          @show-modal="showModalChanges"/>
        </table>
        <button class="add-client btn-reset" id="add"
        @click="showModalAdd">
          Добавить клиента
        </button>

        <ModalWindowAdd v-show="isModalAddVisible"
        v-model:get-clients-data="getClientsData"
        @close-modal-add="closeModal"/>

        <ModalWindowChanges v-show="isModalChangesVisible"
        v-model:client-id="clientId"
        v-model:get-clients-data="getClientsData"
        @close-modal-changes="closeModal"/>
      </div>

<script>
import { mapState } from 'pinia';
import ModalWindowAdd from '@/components/ModalWindowAdd.vue';
import ModalWindowChanges from '@/components/ModalWindowChanges.vue';
import ClientTableTbody from '@/components/ClientTableTbody.vue';
import { useClientsStore } from '../stores/clientsData';
import dateChange from '../helpers/dateChange';
import dateCreation from '../helpers/dateCreation';

export default {
  data() {
    return {
      isModalAddVisible: false,
      isModalChangesVisible: false,
      clientId: null,
    };
  },
  components: {
    ModalWindowAdd,
    ModalWindowChanges,
    ClientTableTbody,
  },
  computed: {
    ...mapState(useClientsStore, ['clientsData', 'isModalChangesOpen']),
    getClientsData() {
      return this.clientsData;
    },
  },
  methods: {
    showModalAdd() {
      this.isModalAddVisible = true;
    },
    showModalChanges() {
      this.isModalAddVisible = true;
    },
    closeModal() {
      this.isModalAddVisible = false;
      this.isModalChangesVisible = false;
    },
  },
};
</script>

ClientTableTbody
<template>
  <tbody class="table__tbody" id="client-list">
    <ClientItem v-for="client in clients" :key="client.id"
    :id="client.id"
    :full-name = client.fullName
    :date="client.date"
    :edit="client.edit"
    :contacts="client.contacts"
    v-model:client-id="currentClientId"
    @show="show"/>
  </tbody>
</template>

<script>
import ClientItem from './ClientItem.vue';

export default {
  data() {
    return {
      currentClientId: null,
    };
  },
  props: ['clients', 'clientId'],
  components: {
    ClientItem,
  },
  methods: {
    show() {
      this.$emit('showModal');
      this.$emit('update:clientId', this.currentClientId);
    },
  },
};
</script>

ClientItem
<template>
  <tr class="table__tbody-tr">
    <td class="table__tbody-tr-td id">
      {{ id }}
    </td>
    <td class="table__tbody-tr-td">
      {{ fullName }}
    </td>
    <td class="table__tbody-tr-td">
      {{ date.slice(0, 10) }}
      <span class="time">
        {{ date.slice(11, 17) }}
      </span>
    </td>
    <td class="table__tbody-tr-td">
      {{ edit.slice(0, 10) }}
      <span class="time">
        {{ edit.slice(11, 17) }}
      </span>
    </td>
    <td class="table__tbody-tr-td">
      <div class="table__tbody-wrapper-contacts">
        <BaseToolTip
        v-for="contact in contacts" :key="contact.selectValue"
        :select-value="contact.selectValue"
        :input-value="contact.inputValue"/>
      </div>
    </td>
    <td class="table__tbody-tr-td edit">
      <button class="btn-reset" @click.prevent="show">
        Изменить
      </button>
    </td>
    <td class="table__tbody-tr-td delete">
      <button class="btn-reset" @click.prevent="deleteClient(id)">
        Удалить
      </button>
    </td>
  </tr>
</template>

<script>
import { mapActions } from 'pinia';
import { useClientsStore } from '@/stores/clientsData';
import BaseToolTip from './BaseToolTip.vue';

export default {
  props: ['id', 'fullName', 'date', 'edit', 'contacts', 'clientId'],
  components: {
    BaseToolTip,
  },
  methods: {
    ...mapActions(useClientsStore, ['deleteClient']),
    show() {
      this.$emit('show');
      this.$emit('update:clientId', this.id);
    },
  },
};
</script>

Также была попытка через Pinia изменять состояние и получать id, но что-то я делал не так, и не получалось изменять состояние через

show() {
  useClientsStore.$state = { isModalChangesOpen: true };
},

и

show() {
  useClientsStore.$patch({ isModalChangesOpen: true });
},

store
import { defineStore } from 'pinia';

export const useClientsStore = defineStore('client', {
  state: () => ({
    clientsData: JSON.parse(localStorage.getItem('clients')) || [],
    clientId: null,
    isModalChangesOpen: false,
  }),
  actions: {
    saveClients() {
      localStorage.setItem('clients', JSON.stringify(this.clientsData));
    },
    deleteClient(id) {
      this.clientsData.map((client, i) => {
        if (client.id === id) {
          this.clientsData.splice(i, 1);
          this.saveClients();
        }

        return this.clientsData;
      });
    },
  },
});
  • Вопрос задан
  • 68 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Не надо никаких v-model, кого показывать в модальном окне - отправляйте наверх эту информацию вместе с событием. Свойство, управляющее видимостью модального окна - пусть оно вместо логического значения хранит id или объект или что там у вас должно показываться в окне, если не null, значит открываем окно. Вот так всё просто.

UPD. Вот вариант с v-model, конечно только на уровне таблицы, в строках всё по-прежнему.

UPD. А вообще, можно полностью отказаться от прокидывания событий наверх. Таблицу исполняем в более общем виде - пусть принимает массив с описанием столбцов, а содержимое ячеек задаётся через слоты, имена которых определяются на основе имён столбцов (по умолчанию выводят данных как есть). В этом случае кнопку можно определить там же, где создаётся экземпляр таблицы. Как это может выглядеть - ваш вариант с отдельным компонентом строки (и, соответственно, прокидыванием в него слотов из компонента таблицы), или, без ненужного усложнения.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы