【问题标题】:Meteor override the click event of an element in a packageMeteor 覆盖包中元素的点击事件
【发布时间】:2015-09-14 07:23:16
【问题描述】:

我试图覆盖 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);
      },

【问题讨论】:

    标签: javascript meteor meteor-autoform


    【解决方案1】:

    您可以使用 stopPropagation 来阻止事件冒泡到自动生成挂钩。

    所以简短的版本:

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

    【讨论】:

      【解决方案2】:

      在绕了一个小时左右的圈子后,我发现了这一点。 Blaze 将它的事件监听器安装在 templateInstance 的父元素中。它们存储在下面的属性称为$blaze_events。它很容易使用,但没有记录。使用方法如下:

      检索事件处理程序

      处理程序存储在一个数组中 ($blaze_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

      <template name="test">
        <p>Hi!</p>
      </template>
      

      client/main.html

      {{ > 测试 }}

      client/main.js

      Template.test.events({
        'click p': function () {
          console.log('PIII')
        }
      })
      
      retrieveBlazeEvent(document.body, 'click', 'p')
      

      移除事件监听器

      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
      }
      

      【讨论】:

      • 谢谢,我已经用我试图覆盖的确切点击事件更新了我的问题,因为您可以看到它不像直接从集合中删除那么简单。再次感谢
      • 这种方法需要我首先知道这个底部引用的是哪个集合,我不知道,因为这不是应用程序集合,而是一个内部包集合,它们临时保存数组项。
      • 花了我三个小时和一些绕圈跑来找到这个解决方案(更新了我的答案)。所以评论前请仔细阅读。希望它有所帮助:) 我在这个过程中学到了很多关于 blaze 的知识,所以无论如何这都是值得的。
      • 不太喜欢在 Blaze 的内部进行黑客攻击,因为它应该是那么简单的事情。在下面发布更短更清晰的答案。此外,恕我直言,删除第 3 方库的事件是一个非常糟糕的主意 - 干杯
      【解决方案3】:

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

        '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                
      
                    }
                  }
      
                }
              });
         }
        }
      

      【讨论】:

      • 这将要求我必须在本地安装包(在应用程序包文件夹下),然后每次有新版本时都会强制手动更新包
      • 显然这是迄今为止最好的方法,谢谢尼克
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 2013-09-10
      • 1970-01-01
      相关资源
      最近更新 更多