Javascript Meteor覆盖包中元素的单击事件

Javascript Meteor覆盖包中元素的单击事件,javascript,meteor,meteor-autoform,Javascript,Meteor,Meteor Autoform,我试图覆盖autoform remove item按钮的按钮单击事件,如下所示,因为我试图显示一条警告消息(在用户可以删除autoform数组中的任何项目之前)。然后,如果用户确认项目移除,则按钮点击事件将正常继续。但我不知道如何覆盖按钮的点击事件,以暂停按钮下方的代码(我无权访问),直到用户确认/拒绝删除?有什么可以帮我的吗?谢谢 Template.salesInvoice.events({ 'click .autoform-remove-item': function(

我试图覆盖autoform remove item按钮的按钮单击事件,如下所示,因为我试图显示一条警告消息(在用户可以删除autoform数组中的任何项目之前)。然后,如果用户确认项目移除,则按钮点击事件将正常继续。但我不知道如何覆盖按钮的点击事件,以暂停按钮下方的代码(我无权访问),直到用户确认/拒绝删除?有什么可以帮我的吗?谢谢

    Template.salesInvoice.events({
       'click .autoform-remove-item': function(e){

            e.preventDefault();

            bootbox.dialog({
              message: "Are you sure you wish to delete this item?",
              title: "New Journal",
              buttons: {
                eraseRecord: {
                  label: "Yes!",
                  className: "btn-danger",
                  callback: function() {

                  }
                },
                doNotEraseRecord: {
                  label: "No!",
                  className: "btn-primary",
                  callback: function() {
                    //Continue with the normal button click event                

                  }
                }

              }
            });
       }

    });
我试图覆盖的单击事件:

      'click .autoform-remove-item': function autoFormClickRemoveItem(event, template) {
        var self = this; // This type of button must be used within an afEachArrayItem block, so we know the context

        event.preventDefault();

        var name = self.arrayFieldName;
        var minCount = self.minCount; // optional, overrides schema
        var maxCount = self.maxCount; // optional, overrides schema
        var index = self.index;
        var data = template.data;
        var formId = data && data.id;
        var ss = AutoForm.getFormSchema(formId);

        // remove the item we clicked
        arrayTracker.removeFromFieldAtIndex(formId, name, index, ss, minCount, maxCount);
      },

在绕圈子跑了一个小时左右后,我发现了这一点。Blaze将其事件侦听器安装在
templateInstance
的父元素旁边。存储它们的属性称为
$blaze\u events
。它很容易使用,但没有文档记录。以下是如何使用它:

检索事件处理程序 处理程序存储在一个数组中(
$blaze\u events.handlers
)。为了找到一个特定的函数,我编写了以下函数:

retrieveBlazeEvent = function retrieveBlazeEvent (parentElement, eventType, selector) {
  var returnHandler
  parentElement.$blaze_events[eventType].handlers.forEach(function (eventHandler) {
    if(eventHandler.selector === selector)
      return (returnHandler = eventHandler) && false
  })
  return returnHandler
}
用法:

client/test.html

删除事件侦听器
retrieveBlazeEvent
返回的事件处理程序具有一个函数
unbind
。下面是一个例子

retrieveBlazeEvent(document.body, 'click', 'p').unbind()
调用此函数后,事件处理程序仍将存在。要恢复它,只需在同一对象上调用
bind

手动触发事件处理程序 假设我们有一个简单的
p
-元素。正在侦听单击事件:

Template.test.events({
  'click p': function () {
    console.log('PIII')
  }
})
要触发事件处理程序,我们需要一个与此选择器匹配的
p
-元素。我们还需要模板实例来检索正确的父节点。然后我们需要调用事件处理程序,将视图作为其上下文。我们还需要为事件创建一个存根,其中包含
currentTarget
。此功能可为您完成以下所有功能:

triggerEvent = function triggerEvent (eventType, elementSelector, context) {
  var context = context || document
  var element = context.querySelector(elementSelector)
  var eventStub = {
    currentTarget: element
  }
  var view = Blaze.getView(element)
  retrieveBlazeEvent(view._domrange.parentElement, eventType, elementSelector)
    .delegatedHandler
    .call(view, eventStub)
  return true
}

您不能在代码中显示引导框确认集合被删除的位置吗?然后,只有在用户确认后才能将其从集合中删除。例如,我认为这应该有帮助:

  'click .autoform-remove-item': function autoFormClickRemoveItem(event, template) {
        bootbox.dialog({
          message: "Are you sure you wish to delete this item?",
          title: "New Journal",
          buttons: {
            eraseRecord: {
              label: "Yes!",
              className: "btn-danger",
              callback: function() {
                  var self = this;
                  var name = self.arrayFieldName;
                  var minCount = self.minCount; // optional, overrides schema
                  var maxCount = self.maxCount; // optional, overrides schema
                  var index = self.index;
                  var data = template.data;
                  var formId = data && data.id;
                  var ss = AutoForm.getFormSchema(formId);
                  arrayTracker.removeFromFieldAtIndex(formId, name, index, ss, minCount, maxCount);
              }
            },
            doNotEraseRecord: {
              label: "No!",
              className: "btn-primary",
              callback: function() {
                //Continue with the normal button click event                

              }
            }

          }
        });
   }
  }

您可以使用StopRopAgation来阻止事件冒泡到自动表单挂钩

因此,简短的版本:

Template.afArrayField.events({
  'click .autoform-remove-item': function(event) {
      if (!confirm('Are you sure you wish to delete this item?')) {
          event.stopPropagation()
      }
  }
})

谢谢,我已经用我试图覆盖的确切点击事件更新了我的问题,正如您所看到的,它不像直接从集合中删除那么简单。再次感谢“删除”按钮仍处于自动形式?因为。这种方法需要我首先知道底部引用的是哪个集合,我不知道,因为这不是应用程序集合,而是一个内部程序包集合,它们在其中临时保存数组项。我花了三个小时和一些循环运行来找到此解决方案(更新了我的答案)。所以在评论之前请仔细阅读。希望能有所帮助:)在这个过程中,我学到了很多关于blaze的知识,所以无论发生什么,这都是值得的。我不是一个热衷于对blaze内部进行黑客攻击的人。在下面贴出简短而清晰的答案。此外,删除第三方库的事件是一个非常糟糕的主意-Cheers这将要求我必须在本地(在application packages文件夹下)安装程序包,然后每次有新版本时将被迫手动更新程序包显然这是迄今为止最好的方法,谢谢Nick
  'click .autoform-remove-item': function autoFormClickRemoveItem(event, template) {
        bootbox.dialog({
          message: "Are you sure you wish to delete this item?",
          title: "New Journal",
          buttons: {
            eraseRecord: {
              label: "Yes!",
              className: "btn-danger",
              callback: function() {
                  var self = this;
                  var name = self.arrayFieldName;
                  var minCount = self.minCount; // optional, overrides schema
                  var maxCount = self.maxCount; // optional, overrides schema
                  var index = self.index;
                  var data = template.data;
                  var formId = data && data.id;
                  var ss = AutoForm.getFormSchema(formId);
                  arrayTracker.removeFromFieldAtIndex(formId, name, index, ss, minCount, maxCount);
              }
            },
            doNotEraseRecord: {
              label: "No!",
              className: "btn-primary",
              callback: function() {
                //Continue with the normal button click event                

              }
            }

          }
        });
   }
  }
Template.afArrayField.events({
  'click .autoform-remove-item': function(event) {
      if (!confirm('Are you sure you wish to delete this item?')) {
          event.stopPropagation()
      }
  }
})