草庐IT

javascript - 在指令中监听表单提交事件

coder 2024-07-22 原文

我想在指令中监听表单提交。假设我有这样的指令:

app.directive('myDirective', function () {
    return {
        restrict: 'A',
        require: '^form',
        scope: {
            smth: '='
        },
        link: function (scope, el, attrs, formCtrl) {
            scope.$watch(function(){
                return formCtrl.$submitted;
            },function(currentValue){
                console.log('submitted');
            });
        }
    }
});

用上面的方法我可以看到第一次提交,但不能看到其余的。我试图做这样的事情:

scope.$watch(function () {
    return formCtrl.$submitted;
}, function (currentValue) {
    if (currentValue) {
        console.log('submitted');
        formCtrl.$setPristine(); // Watch this line!
    }
});

但问题是,如果我在一个表单中多次使用该指令,它只对第一次使用有效。 我想知道的是是否有类似 formCtrl.onsubmit(...) 的东西或任何解决方法来获得相同的功能。在此先感谢您的帮助...

最佳答案

您可以创建一个与 form 指令同名的指令,而不是观察 $submitted 属性,该指令附加了一个表单提交的事件处理程序广播一个 Angular 事件,您可以在 myDirective 指令中收听该事件。您不必担心覆盖 form 指令的 Angular 实现,它只会附加您的行为,不会覆盖内置实现。

DEMO

注意:您也可以选择不将功能附加到 form 指令,而是选择另一个指令名称,只需确保将该指令名称附加为表单标记中的属性即可触发事件.

Javascript

.directive('form', function() {

  return {
    restrict: 'E',
    link: function(scope, elem) {
      elem.on('submit', function() {
         scope.$broadcast('form:submit');
      });
    }
  };

})

.directive('myDirective', function() {
  return {
    require: '^form',
    link: function(scope, elem, attr, form) {
      scope.$on('form:submit', function() {
        form.$setPristine();
      });
    }
  };
});

更新

鉴于下面评论中提出的问题:

what's the most efficient way to check if the element that has "my-directive" attribute has "my-form" (if I name "form" directive to "myForm") attribute in it's parent form? So I can either use "myDirective" with or without "myForm" (and behave accordingly of course)

有几种方法可以做到这一点:

  1. 在编译阶段使用 myForm 指令中的 .data() 方法,并在 myDirective 的链接函数中访问它如果在 form 指令中分配的数据存在,则使用 .inheritedData() 方法。

请注意,我在 myForm 指令的广播中传递了 form Controller 。这确保您收到来自 form 元素的父表单 Controller 。在某些用例中,您可以通过 ng-form 在嵌套表单中使用 myDirective,而不是设置 form.$setPristine() 到您要设置 ngForm 表单 Controller 的 form 元素表单 Controller 。

DEMO

  .directive('myForm', function() {

    return {
      require: 'form',
      compile: function(tElem, tAttr) {

        tElem.data('augmented', true);

        return function(scope, elem, attr, form) {
          elem.on('submit', function() {
             scope.$broadcast('form:submit', form);
          });
        }
      }
    };

  })

  .directive('myDirective', function() {
    return {
      link: function(scope, elem, attr) {

        if(!elem.inheritedData('augmented')) {
          return;
        }

        scope.$on('form:submit', function(event, form) {
          console.log('submit');
          form.$setPristine();
        });
      }
    };
  });
  1. 另一种方式可能是针对此特定用例高度优化的方式。在 myForm 指令中创建一个 Controller ,该指令存储要在触发表单事件时迭代的表单事件处理程序。而不是使用 $broadcast Angular 事件,它实际上比下面的实现慢,因为它遍历从 form 元素到最后一个范围链的每个范围。下面的 myForm Controller 创建了自己的机制来存储事件处理程序。正如#1 中所实现的,使用 .data() - inheritedData() 很慢,因为 myDirective 被埋得很深并且嵌套在很多地方元素,因为它向上遍历 DOM,直到找到特定的 data。使用下面的实现,您可以检查父级中是否存在所需的 ?^myForm Controller ,注意 ? 它代表可选要求。此外,在 myForm 指令中将范围设置为 true 允许您使指令可重用,例如在一个页面中有多个 myForm 指令..

DEMO

  .directive('myForm', function() {

    return {
      require: ['form', 'myForm'],
      scope: true,

      controller: function() {

        this.eventHandlers = {
          submit: [],
          change: []
        };

        this.on = function(event, handler) {
          if(this.eventHandlers[event]) {
            this.eventHandlers[event].push(handler);
          }
        };

      },

      link: function(scope, elem, attr, ctrls) {
        var form = ctrls[0],
            myForm = ctrls[1];


        angular.forEach(myForm.eventHandlers, function(handlers, event) {
          elem.on(event, function(eventObject) {
            angular.forEach(handlers, function(handler) {
              handler(eventObject, form);
            });
          });
        });

      }

    };

  })

  .directive('myDirective', function() {
    return {
      require: '?^myForm',
      link: function(scope, elem, attr, myForm) {

        if(!myForm) {
          return;
        }

        myForm.on('submit', function(event, form) {
          console.log('submit');
          form.$setPristine();
        });
      }
    };
  });

关于javascript - 在指令中监听表单提交事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26383507/

有关javascript - 在指令中监听表单提交事件的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  3. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  4. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  5. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  6. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  7. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

  8. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

    例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

  9. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  10. ruby-on-rails - 如何在 Rails 中添加禁用的提交按钮 - 2

    我在ruby​​表单中有一个提交按钮f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id"我想在不使用任何javascript的情况下通过ruby​​禁用此按钮 最佳答案 添加disabled:true选项。f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id",disabled:true 关于ruby-on-rails-如何在Rails中添加禁用的提交按钮,我们在St

随机推荐