【问题标题】:Clicking a button within a form causes page refresh单击表单中的按钮会导致页面刷新
【发布时间】:2021-09-30 18:13:17
【问题描述】:

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

  1. 如果我删除ng-click,该按钮不会导致页面刷新。
  2. 如果我注释掉函数中的代码,它不会导致页面刷新。
  3. 如果我使用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";
};

【问题讨论】:

标签: javascript angularjs


【解决方案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 逻辑来以应用程序特定的方式处理表单提交。出于这个原因,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" 来解决了这个问题,并且成功了。

            【讨论】:

              猜你喜欢
              相关资源
              最近更新 更多