如何等到模态关闭并根据单击确定或取消继续执行?

Posted

技术标签:

【中文标题】如何等到模态关闭并根据单击确定或取消继续执行?【英文标题】:How to wait until modal is closed and continue execution based on either OK or CANCEL was clicked? 【发布时间】:2019-06-29 05:11:14 【问题描述】:

算法:

    我发现两个对象数组之间的区别(什么是新的、什么是删除的、重命名的等)。差异存储在data[1-5] 基于#1,我为模态准备了一个文本摘要(文本对象) 通知用户发现了什么不同。此摘要存储在someDataToShowInModal。 发现差异时,必须向用户显示带有摘要的模式。用户应接受(单击确定)或拒绝(单击取消)以应用更改。

    问题:如何等到用户点击模态框的 OK 或 CANCEL 按钮?

    在代码中我展示了两种可能的解决方案,但不知道如何实现它们:

      将模态包装到 Promise 中。

      使用state.doSave 并以某种方式等待它被myModalComponent 更改。

    如果用户单击“确定”,则应用更改。

下面是伪代码,显示了我尝试实现的逻辑:

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>

我知道一旦通过 OK 按钮关闭模态框后如何调用函数,但在这种情况下,有必要在 vuex 中临时保存数据 [1-5] 以便在被调用函数中再次选择它们,我想要使用更简单的方法来避免它。

【问题讨论】:

由于 javascript 的异步特性,您将无法真正“等待”直到模式关闭;您将不得不实现回调或一些Promise。如果您使用的是现代 JS,您可以尝试使用 await,但在幕后,它将使用 Promise 是的,我知道。这就是您可以在我的代码中找到async/await 的原因。我会澄清的。谢谢。 我明白了...我现在无法编写示例代码,但要使用Promise,您需要将 OK/CANCEL 按钮的单击事件捕获封装在内部Promise,点击事件本身需要调用resolve函数。 这与我正在谈论的内容相似,但不是从某个发射器捕获事件,而是从按钮捕获事件:***.com/a/29933215/679240 【参考方案1】:

我想为您提供一些重构:)

1) 商店的操作不应该知道接口(服务器端渲染问题,...) - 不好的做法。

2) 最好将 modal 的数据存储在 modal 的父组件中。 这是一个例子: 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;
,

【讨论】:

1.我不需要 s-s-r,至少在不久的将来。 2. 好像漏了// ... code which handles data from data[1-5]。这里的关键部分是data[1-5](即在第一部分我发现了一个差异,然后我向用户展示了这个差异,在第二部分我处理来自data1、data2 等的数据)。如我所见,如果使用您的代码,我需要在第一步将临时 data[1-5] 存储在某处,并在第二步获得访问权限。 store.dispatch('saveModalData', this.modalData); 处理您的数据[]。您可以从 prepareDataToShowInModal 返回所需的值 -> 将其存储在 this.modalData -> 并通过 saveModalData 保存到存储。【参考方案2】:

如果您使用 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();

【讨论】:

我关于 VueJs 的问题,而不是关于 Angular 的问题(您可能会在此处被否决)。但是,我理解您试图向我展示的内容,但这并不能解决我的问题。【参考方案3】:

感谢post,找到了如何通过 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”(示例名称)调用,结果打开了模式。如果我们在没有点击 OK 按钮的情况下打开/关闭 modal 5 次,我们也会观看 state.doSave 5 次,当第 6 次打开 OK 按钮后,data[1-5] 将被处理 6 次。所以,如果modal在没有点击OK按钮的情况下关闭,我们需要取消关注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>

【讨论】:

以上是关于如何等到模态关闭并根据单击确定或取消继续执行?的主要内容,如果未能解决你的问题,请参考以下文章

如何在提交时重新加载页面

知道何时在 Apple Watch 模态界面控制器中单击取消按钮

如何关闭表格

在 Jquery 模态窗口关闭时重置 iframe src

Qt 之 模态非模态半模态窗口的介绍及 实现QDialog的exec()方法

iOS UISearchController:等到 UISearchController 在取消搜索后被解除