Как дождаться закрытия модального окна и продолжить выполнение, нажав OK или ОТМЕНА? - PullRequest
0 голосов
/ 05 февраля 2019

Алгоритм:

  1. Я нахожу разницу между двумя массивами объектов (что нового, что удалено, переименовано и т. Д.).Различия хранятся в data[1-5]
  2. На основе № 1 я готовлю текстовую сводку (объекты текста) для модального окна, чтобы уведомить пользователя о том, какая разница обнаружена.Эта сводка хранится в someDataToShowInModal.
  3. Когда обнаружена разница, пользователю необходимо показать модальное с сводкой.Пользователь должен принять (щелкнуть ОК) или отклонить (щелкнуть ОТМЕНА), чтобы применить изменения.
  4. ВОПРОС : Как ждать, пока пользователь нажмет кнопку ОК или ОТМЕНА модала?

    В коде я показываю два возможных решения, но не знаю, как их реализовать:

    1. Обернуть модал в Promise.

    2. Использованиеstate.doSave и каким-то образом подождать, пока оно не изменится на myModalComponent.

  5. Применить изменения, если пользователь нажмет OK.

Ниже приведен псевдокод, который показывает логику, которую я пытаюсь реализовать:

state.js

modalTextSummary = {}

action.js

async myAction ({ state }) {
  let modalClosed
  let someDataToShowInModal = {}

  let data1 = []
  let data2 = []
  let data3 = []
  let data4 = []
  let data5 = []

  // #1. Push difference to "data[1-5]"
  data1.push(xyz1)
  data2.push(xyz2)
  data3.push(xyz3)
  data4.push(xyz4)
  data5.push(xyz5)

  // #2. Based on data[1-5] prepare "someDataToShowInModal"
  someDataToShowInModal = {xyz}

  // #3. We change "state.modalTextSummary" and by this we open
  // a Modal (because "myModalCompont" has "watch: {modalTextSummary}")
  state.modalTextSummary = someDataToShowInModal

  // #4. HOW TO WAIT UNTIL USER CLICKS Modal's "OK" or "CANCEL"?

  // v1:
  // something like...
  modalClosed = await myModalComponent

  // v2:
  // I can add "state.doSave = ''" which can be
  // set by "myModalComponent" to either 'OK' or 'CANCEL', but how
  // in this case I can wait for state changes?
  modalClosed = await state.doSave !== ''

  // #5. Apply changes
  if (modalCloses === 'OK') {
    // ... code which handles data from data[1-5]
  }
}

myModalComponent.js

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState([
      'modalTextSummary'
    ])
  },

  watch: {
    modalTextSummary: function () {
      if (this.modalTextSummary !== {}) {
        // Here I show bootstrap-vue modal
      }
    }
  }
}
</script>

Я знаю, как вызывать функцию после закрытия модальной кнопки ОК, но в этом случае необходимовременно сохранить данные [1-5] в vuex, чтобы снова выбрать их внутри вызываемой функции, и я хочу избежать этого, используя более простой подход.

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Я хочу предложить вам сделать какой-нибудь рефакторинг:)

1) Действия магазина НЕ ДОЛЖНЫ знать об интерфейсе (проблемы рендеринга на стороне сервера, ...) - плохая практика.

2) Лучше хранить модальные данные в родительском компоненте модала.Вот пример: https://jsfiddle.net/yyx990803/70yyx8z2/

Тогда вы сможете сделать что-то вроде этого (псевдокод):

<my-modal
    v-if="showModal"
    @cancel="processModalCancel"
    @submit="processModalSubmit"
    >
    <!-- mutating-manipulations with modalData -->
</my-modal>

---

openModal() {
    this.showModal = true;
    this.modalData = store.dispatch('prepareDataToShowInModal'); // myAction, first part
},
processModalCancel() {
    this.showModal = false;
    this.modalData = null;
},
processModalSubmit() {
    this.showModal = false;
    store.dispatch('saveModalData', this.modalData); // myAction, second part
    this.modalData = null;
},
0 голосов
/ 08 февраля 2019

Нашел способ, как реализовать это через v2, благодаря этой публикации .

gleam ответ короче и чище, поэтому вы должны предпочесть его решение,Мое решение ниже опубликовано только для образовательных целей.

state.js

modalTextSummary = {}
doSave = false

action.js

// My 'store' file is at the root. Where is yours - I do not know :)
import store from '@/store'

async myAction ({ state }) {
  state.doSave = false

  let modalClosed
  let someDataToShowInModal = {}

  let data1 = []
  let data2 = []
  let data3 = []
  let data4 = []
  let data5 = []

  // #1. Push difference to "data[1-5]"
  data1.push(xyz1)
  data2.push(xyz2)
  data3.push(xyz3)
  data4.push(xyz4)
  data5.push(xyz5)

  // #2. Based on data[1-5] prepare "someDataToShowInModal"
  someDataToShowInModal = {xyz}

  // #3. We change "state.modalTextSummary" and by this we open
  // a Modal (because "myModalCompont" has "watch: {modalTextSummary}")
  state.modalTextSummary = someDataToShowInModal

  // #4. Wait until user closes modal or clicks OK
  const unwatch = store.watch(
    (state) => state.doSave,
    (value) => {

      // #5. Apply changes
      if (value === true) {
        unwatch()
        // ... code which handles data from data[1-5]

      } else if (value === 'unwatch') {
        unwatch()
      }
    }
  )
}

Зачем нам нужно unwatch()?

В моем случае myAction вызывается "someButton" (имя примера) и в результате открывается модально.Если мы открываем / закрываем модальные 5 раз без нажатия кнопки ОК, мы будем смотреть state.doSave также 5 раз, и когда после 6-го открытия будет нажата кнопка ОК, data[1-5] будет обработано 6 раз.Таким образом, если модальное окно закрыто без нажатия кнопки ОК, нам нужно отменить state.doSave.

myModalComponent.js

<template>
  <b-modal
    ref="myModal"
    ok-title="OK"
    cancel-title="Close"
    @keydown.native.enter="closeModalAndSave"
    @ok="closeModalAndSave"
    @hide="closeModalAndUnwatch"
  >
    {{ modalTextSummary }}
  </b-modal>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  computed: {
    ...mapState([
      'modalTextSummary'
    ])
  },

  watch: {
    modalTextSummary: function () {
      if (this.modalTextSummary !== {}) {
        this.$refs.myModal.show()
      }
    }
  },

  methods: {
    ...mapMutations('media', [
      'doSave'
    ]),

    closeModalAndUnwatch (bvEvent) {
      // "this.$refs.myModal.hide()" fires @hide with "bvEvent.trigger === null".
      // We need to 'unwatch' just when bvEvent.trigger === 'cancel' or 'backdrop',
      // or 'header-close', ie not null.
      if (bvEvent.trigger !== null) {
        this.doSave('unwatch')
      }
    },

    closeModalAndSave () {
      this.doSave(true)
      this.$refs.myModal.hide()
    }
  } // End of "methods"
}
</script>
0 голосов
/ 05 февраля 2019

Если вы используете bsModal, вы должны написать отдельные привязки функций для обеих кнопок, пока пользователь не нажмет ни одну из кнопок или не щелкнет за пределами модального режима, который будет оставаться открытым.

<button (click)="confirm()"></button>
<button (click)="Cancel()"></button>
import { BsModalRef} from 'ngx-bootstrap';
constructor(){public modalRef: BsModalRef}

confirm(){
//do anything 
this.modalRef.close();
}

Cancel(){
//do anything
this.modalRef.close();
}
...