单击表单中的按钮会导致页面刷新

Posted

技术标签:

【中文标题】单击表单中的按钮会导致页面刷新【英文标题】:Clicking a button within a form causes page refresh 【发布时间】:2012-09-01 10:26:14 【问题描述】:

我在 Angular 中有一个表单,里面有两个按钮标签。一键在ng-click 上提交表单。另一个按钮纯粹用于使用ng-click 进行导航。但是,当单击第二个按钮时,AngularJS 会导致页面刷新,从而触发 404。我在函数中放置了一个断点,它正在触发我的函数。如果我执行以下任何操作,它就会停止:

    如果我删除ng-click,该按钮不会导致页面刷新。 如果我注释掉函数中的代码,它不会导致页面刷新。 如果我使用href="" 将按钮标签更改为锚标签(<a>),则不会导致刷新。

后者似乎是最简单的解决方法,但为什么 AngularJS 甚至在我的函数之后运行任何导致页面重新加载的代码?好像是个bug。

这是表格:

<form class="form-horizontal" name="myProfile" ng-switch-when="profile">
  <fieldset>
    <div class="control-group">
      <label class="control-label" for="passwordButton">Password</label>
      <div class="controls">
        <button id="passwordButton" class="secondaryButton" ng-click="showChangePassword()">Change</button>
      </div>
    </div>

    <div class="buttonBar">
      <button id="saveProfileButton" class="primaryButton" ng-click="saveUser()">Save</button>
    </div>
  </fieldset>
</form>

这里是控制器方法:

$scope.showChangePassword = function() 
  $scope.selectedLink = "changePassword";
;

【问题讨论】:

看看这是否是您的问题github.com/angular/angular.js/issues/1238(不幸的是,我对 github 的了解不够,无法判断此修复程序是否在 1.0.1 版本中)。 我看到了那个,但我没有更改位置,所以我认为它不适用。除非这个其他按钮以某种方式导致它提交,但它没有定义为提交类型,并且当我取消 ng-click 时,该按钮不会提交表单。 如果你能提供这个问题的工作演示,那就太好了。也许从:Angular Plnkr 欺骗***.com/questions/932653/… 好像是重复的。 ***.com/questions/16703215/… 【参考方案1】:

如果您查看W3C specification,似乎显而易见的做法是在您不想提交按钮元素时用type='button' 标记它们。

特别要注意的是它说的地方

未指定类型属性的按钮元素与类型属性设置为“提交”的按钮元素表示相同的东西

【讨论】:

我遇到了与 OP 相同的问题,但我的按钮具有指定的类型 - 仍然单击会导致刷新。还有其他我可以看的地方吗? 这向我表明您的问题出在 javascript 中。我的回答要解决的问题更多是 dom 和浏览器之间的问题。一些处理您的按钮单击的 javascript 可能会导致您看到重新加载。狩猎快乐;) 这正是我想要的。我的页面很烦人,因为它应该只显示错误而不提交。 我的按钮标有 type="button" 并且也有问题。在我的 ng-click 处理程序中,我有 $event.stopPropagation()。当我删除它时,它不会重新加载。不过我需要它。任何想法为什么会导致页面重新加载?! @freshfelicio:尝试同时添加$event.preventDefault(),这对我的情况有所帮助。但我没有解释为什么:-\【参考方案2】:

您可以尝试阻止默认处理程序:

html:

<button ng-click="saveUser($event)">

js:

$scope.saveUser = function (event) 
  event.preventDefault();
  // your code

【讨论】:

不错!它真的很适合我的场景! 这对我们有用,在 SharePoint 表单中使用 AngularJS 时。我确实必须添加“event.stopPropagation();”不过也一样。【参考方案3】:

您应该在&lt;form&gt; 标签中声明属性ng-submit=expression

来自 ngSubmit 文档 http://docs.angularjs.org/api/ng.directive:ngSubmit

启用将角度表达式绑定到 onsubmit 事件。

此外,它会阻止默认操作(对于表单而言,这意味着将请求发送到服务器并重新加载当前页面)。

【讨论】:

另外,请确保您没有在表单上设置 'action' 属性:form(action="/login", lng-submit="login()") 因为这会使页面刷新即使您设置了 ng-submit。 提交表单并阻止默认操作 由于表单在客户端 Angular 应用程序中的作用与经典往返应用程序不同,因此浏览器最好不要将表单提交转换为整页reload 将数据发送到服务器。相反,应该触发一些 javascript 逻辑来以应用程序特定的方式处理表单提交。出于这个原因,除非
元素指定了 action 属性,否则 Angular 会阻止默认操作(向服务器提交表单)。 - docs.angularjs.org/api/ng.directive:form
我有一个带有 ng-submit=expression 的表单和一个带有 type="submit" 的按钮。除了在 BB10 上外,工作正常。如果我使用 BB10 键盘的提交,那么页面将刷新。如果我使用我在表单中声明的​​按钮,它可以正常工作。 这对我不起作用。我完全按照指示进行。该页面仍在回发【参考方案4】:

我使用指令来防止默认行为:

module.directive('preventDefault', function() 
    return function(scope, element, attrs) 
        angular.element(element).bind('click', function(event) 
            event.preventDefault();
            event.stopPropagation();
        );
    
);

然后,在 html 中:

<button class="secondaryButton" prevent-default>Secondary action</button>

该指令也可以与&lt;a&gt; 和所有其他标签一起使用

【讨论】:

+1 谢谢!当您无权访问 &lt;form&gt; 标记并因此无法使用 ng-submit 指令时,这很有帮助。 谢谢你,但我还需要取消指令中的 ng-click 这样也可以防止表单触发 ng-submit 回调,对吧?【参考方案5】:

您可以保留&lt;button type="submit"&gt;,但必须删除&lt;form&gt; 的属性action=""

【讨论】:

【参考方案6】:

我想知道为什么没有人提出可能最简单的解决方案:

不要使用&lt;form&gt;

&lt;whatever ng-form&gt; 恕我直言做得更好,并且没有 HTML 表单,浏览器本身无需提交任何内容。使用角度时,这正是正确的行为。

【讨论】:

如何在没有表单标签的情况下强制点击表单有效? @RizwanPatel 我猜,我不明白,但是使用ng-form=someForm,你会得到$scope.someForm,它有一个$valid 字段。所以我通过&lt;button ng-disabled="!someForm.$valid"&gt; 得到了我需要的一切。【参考方案7】:

向您的表单添加操作。

&lt;form action="#"&gt;

【讨论】:

【参考方案8】:

此答案可能与问题没有直接关系。仅适用于使用脚本提交表单的情况。

根据ng-submit code

 var handleFormSubmission = function(event) 
  scope.$apply(function() 
    controller.$commitViewValue();
    controller.$setSubmitted();
  );

  event.preventDefault();
;

formElement[0].addEventListener('submit', handleFormSubmission);

它在表单上添加了提交事件监听器。 但是通过调用 form.submit() 发起提交时,不会调用提交事件处理程序。在这种情况下,ng-submit 不会阻止默认操作,您必须在 ng-submit 处理程序中自己调用 preventDefault;

为了提供一个合理确定的答案,HTML 表单提交算法第 5 项指出,如果表单没有通过调用 submit 方法提交,它只会调度提交事件(这意味着它只会在通过按钮提交时调度提交事件或其他隐式方法,例如在焦点位于输入类型文本元素上时按 Enter)。

见Form submitted using submit() from a link cannot be caught by onsubmit handler

【讨论】:

【参考方案9】:

第一个按钮提交表单,第二个不提交

<body>
<form  ng-app="myApp" ng-controller="myCtrl" ng-submit="Sub()">
<div>
S:<input type="text" ng-model="v"><br>
<br>
<button>Submit</button>
//Dont Submit
<button type='button' ng-click="Dont()">Dont Submit</button>
</div>
</form>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) 
$scope.Sub=function()

alert('Inside Submit');


$scope.Dont=function()

$scope.v=0;

);
</script>

</body>

【讨论】:

【参考方案10】:

只需在app.module.ts 文件的imports 数组中添加FormsModule, 并在这个文件的顶部添加import FormsModule from '@angular/forms';...这样就可以了。

【讨论】:

【参考方案11】:

我也遇到了同样的问题,但很高兴我通过将类型从 type="submit" 更改为 type="button" 来解决此问题,并且成功了。

【讨论】:

以上是关于单击表单中的按钮会导致页面刷新的主要内容,如果未能解决你的问题,请参考以下文章

更新面板中的链接按钮导致页面刷新

页面刷新后保留值

Django阻止页面刷新

解决button按钮点击会刷新页面以及触发表单BUG

如何避免在asp.net中的按钮单击事件后页面刷新

当通过链接或后退按钮打开时,强制 JSF 刷新页面/视图/表单