Как использовать v-для и излучаемые значения вместе?

#vue.js #vuejs2

Вопрос:

У меня есть таблица, в которой показан список таких стран (также ссылка на полный код и поле ниже).:

введите описание изображения здесь

При нажатии кнопки «Обзор» появляется модальный режим, и пользователь может просмотреть некоторые данные о стране, а затем выбрать один из следующих вариантов:

[mark as ready] [mark as reject] [mark as pending]

Основываясь на его выборе, мне нужно отправить идентификатор страны обратно родительскому компоненту, чтобы теперь мы могли отображать статус для этой конкретной страны как «Отклонено», «Готово» или «Ожидает».

В чем мне нужна помощь, так это в том, как я могу логически сделать это как можно проще, не усложняясь (в чем я ужасен).

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

Позвольте мне объяснить:

Вот моя таблица с данными по странам и кнопками для просмотра: App.vue :

 <template>
  <div id="app" class="container mt-5">
    <table class="table">
      <thead>
        <tr>
          <th scope="col">Country</th>
          <th scope="col">Status</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="country in countryChanges" :key="country.id">
          <td>{{ country.name }}</td>
          <td>
            <template v-if="ready">
              <button :href="`#modal_${country.id}`" data-bs-toggle="modal">
                Ready
              </button>
            </template>
            <template v-else-if="rejected">
              <button :href="`#modal_${country.id}`" data-bs-toggle="modal">
                Rejected
              </button>
            </template>
            <template v-else>
              <button :href="`#modal_${country.id}`" data-bs-toggle="modal">
                Review
              </button>
            </template>
          </td>
          <AppModal :country="country" @set-as-ready="setAsReady"> </AppModal>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import AppModal from "@/components/AppModal.vue";
import changedCountryData from "@/assets/data.json";
export default {
  name: "AdminDashboard",
  components: {
    AppModal,
  },
  data() {
    return {
      countryChanges: [],
      ready: false,
      rejected: false,
    };
  },
  async created() {
    this.countryChanges = changedCountryData;
  },
  methods: {
    setAsReady(id) {
      
    },
  },
};
</script>
 

Вот модальный экран для каждого подробного представления страны:
AppModal.vue :

 <template>
  <section
    class="modal fade"
    :id="`modal_${country.id}`"
    tabindex="-1"
    aria-labelledby="appModal"
    aria-hidden="true"
  >
    <div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title fw-bold fs-2">
            <slot name="heading"></slot>
          </h5>
          <button
            type="button"
            class="btn-close"
            data-bs-dismiss="modal"
            aria-label="Close"
          ></button>
        </div>
        <div class="modal-body">
          <div class="container-fluid">
            <ul class="list-inline fw-bold mb-4">
              <li class="list-inline-item me-4">
                <span class="badge rounded-pill bg-light text-secondary"
                  >Baseline Type</span
                >
                <slot name="baselineType"></slot>
              </li>
              <li class="list-inline-item me-4">
                <span class="badge rounded-pill bg-light text-secondary">
                  Submitter</span
                >
                Doe, John
              </li>
              <li class="list-inline-item me-4">
                <span class="badge rounded-pill bg-light text-secondary">
                  Submitted</span
                >
                March 2, 2021
              </li>
              <li class="list-inline-item">
                <span class="badge rounded-pill bg-light text-secondary me-2"
                  >Status</span
                >
                <span class="badge rounded-pill bg-warning text-dark"
                  >Review Changes</span
                >
              </li>
            </ul>

            <table class="table table-bordered table-striped">
              <thead class="table-dark fs-5">
                <tr>
                  <th scope="col" class="text-muted">Field/Entity</th>
                  <th scope="col">{{ country.name }}</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <th scope="row">Full Name</th>
                  <td>
                    Original Value
                    <div class="ps-2 fw-bold text-success">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="16"
                        height="16"
                        fill="currentColor"
                        class="bi bi-arrow-return-right"
                        viewBox="0 0 16 16"
                      >
                        <path
                          fill-rule="evenodd"
                          d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z"
                        />
                      </svg>
                      Updated Value
                    </div>
                  </td>
                </tr>
                <tr>
                  <th scope="row">Local Short Name</th>
                  <td>
                    Original Value
                    <div class="ps-2 text-success fw-bold">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="16"
                        height="16"
                        fill="currentColor"
                        class="bi bi-arrow-return-right"
                        viewBox="0 0 16 16"
                      >
                        <path
                          fill-rule="evenodd"
                          d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z"
                        />
                      </svg>
                      Updated Value
                    </div>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>

        <div class="modal-footer border-top-0">
          <button type="button" class="btn btn-link" data-bs-dismiss="modal">
            Close
          </button>
          <button
            type="button"
            class="btn btn-success"
            data-bs-dismiss="modal"
            @click="setAsReady(country)"
          >
            Mark as Ready
          </button>
          <button type="button" class="btn btn-danger">Mark as Reject</button>
          <button type="button" class="btn btn-warning">Mark as Pending</button>
        </div>
      </div>
    </div>
  </section>
</template>

<script>
export default {
  props: {
    country: {
      type: Object,
      required: true,
    },
  },
  methods: {
    setAsReady(country) {
      // console.log(country.id);
      this.$emit("set-as-ready", country.id);
    },
  },
};
</script>
 

Если, например, нажата кнопка «Отметить как готовую», я хочу затем отобразить обновленную кнопку со статусом «Готов» для этой страны (в данном примере, Мексика) примерно так:

введите описание изображения здесь

У кого-нибудь есть совет, как я могу сделать это логично и эффективно? У меня есть демо-версия codesandbox, доступная здесь: https://codesandbox.io/s/tender-black-zn9nt?file=/src/App.vue

Ответ №1:

Самый простой подход-это управление центральным состоянием данных. Установите новое свойство «статус» для элементов таблицы. Затем переключите это значение в зависимости от события, вызванного из таблицы.

 <template v-if="country.status === 1">
    <button :href="`#modal_${country.id}`" data-bs-toggle="modal">
       Ready
    </button>
</template>



 methods: {
    setAsReady(id) {
      let country = this.countryChanges.find((e) => e.id === id);
      country.status = 1;
    },
  },
 

См. поле Рабочие кодыи: https://codesandbox.io/s/dry-water-gl2q9?file=/src/App.vue

Комментарии:

1. Спасибо, это хорошо работает. Я взял ваш codesandbox и изменил его . Вы видите что-нибудь неправильное в этом подходе? codesandbox.io/s/patient-feather-uoqs9?file=/src/App.vue

2. Я посмотрел на код и коробку. это именно то, что я хотел сказать. выглядит чисто и просто. ваше здоровье!