小编典典

AngularJS与Ajax表单提交需要单击两次

ajax

我需要从HTML页面执行以下活动:

  1. 用户输入电子邮件和密码进行注册
  2. 用户单击时将表格发送到控制器 Submit
  3. Control使用AJAX创建到RESTful Server的JSON请求,服务器进行相应的响应。
  4. 根据服务器的响应,用户应获得警报窗口,并register.html在“提交”下方的当前页面()上显示一条消息。如果是“成功-已注册”或“失败-无法注册”。

但是,目前它的工作方式如下:1),2),3)正常工作。

  1. 用户在第一次单击Submit相应的消息时会得到警报窗口。

  2. 用户仅在Submit 再次 单击时获得打印的消息,但再次显示警告窗口。

如果我alert('Something')从JS中删除,则必须单击两次以将消息打印在register.html

另外,我想提醒您注意,单击两次也会使服务器调用两次。它的行为就好像在服务器调用后已暂停,然后打印我应该单击“提交”的消息一样。

register.html

<div class='container'>
    <div class='col-md-12'>
        <div class='fill' ng-controller="registerController">
            <form name="userForm" ng-submit="submitForm(userForm.$valid,user)" novalidate>
                <!-- ALL FORM ELEMENTS HERE -->
                <button type="submit" class="btn btn-primary" ng-disabled="userForm.$invalid" ng-click="showme=true">
                    Submit
                </button>
                <div class="wrapper">
                    <h3 ng-show="showme"><em>{{msgalert}}</em></h3>
                </div>
            </form>
        </div>
    </div>
</div>

我的JS控制器看起来像这样 stackoverflow_q3.js

// create angular controller
var register = angular.module('Main-app');
register.controller('registerController', function ($scope, $http, $location) {

    // function to submit the form after all validation has occurred            
    $scope.submitForm = function (isValid, user) {
        console.log('Stackoverflow JS func caled');
        var regData = {
            "email": user.email,
            "password": user.password1
        };

        var jsonData = JSON.stringify(regData);
        var request = $.ajax({
            url: 'myurl',
            type: 'POST',
            data: jsonData,
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            dataType: 'json',
            complete: function (response) {
                console.log(response.responseText);
                if (response.responseText == 'success') {
                    console.log('Registration Success');
                    alert('Success');
                    $scope.msgalert = 'Registration Success, Proceed to Login and Continue';
                } else if (response.responseText == 'fail') {
                    alert('registration failed');
                    $scope.msgalert = 'Registration Failed, Please try again';
                }
            }
        });
    };
});

另外index.html我提到了控制器:

<!-- HTML -->
<!DOCTYPE html>
<html ng-app="Main-app">
<!--  Controllers  -->
<script src="js/controllers/stackoverflow_q3.js" type="text/javascript"></script>

    <!-- Other elements -->

</html>

知道如何通过一次“提交”单击即可完成所有这些活动吗?


阅读 298

收藏
2020-07-26

共1个答案

小编典典

只需执行以下操作:$timeout在控制器中注入服务并将代码包装如下:

complete: function(response) {
    console.log(response.responseText);
    $timeout(function() {
        if (response.responseText == 'success') {
            console.log('Registration Success');
            alert('Success');
            $scope.msgalert = 'Registration Success, Proceed to Login and Continue';

        } else if (response.responseText == 'fail') {
            alert('registration failed');
            $scope.msgalert = 'Registration Failed, Please try again';
        }
    });
}

另外,像这样更改您的HTML代码:

<h3 ng-show="msgalert"><em>{{msgalert}}</em></h3>

因此在Angular中有一个摘要循环的概念。如果您正在Angular上下文之外进行某些操作(例如您正在使用jQuery AJAX来获取数据并更新的$
scope变量msgalert),我们必须告诉Angular数据中已有更改。

因此,在您从服务器获得响应并更新了之后msgalert,Angular不会意识到该更改,因为它不在Angular的上下文之外,因此触发了Angular的新摘要循环,并且视图未更新。

之所以会这样,是因为当您再次单击表单中的“提交”按钮时,将在后台触发Angular的摘要循环,然后显示您的实际消息。

为了解决这个问题,我们使用服务将您的自定义(外部角度上下文)代码包装到Angular的上下文中,该$timeout服务立即通知Angular值msgalert已更改

(可选)您可以$scope.$apply()if-else条件之后编写after,但是有时会引发异常,digest cycle is already in progress因为调用$scope.$apply(),我们会手动触发Angular的摘要周期。这就是为什么$timeout服务更清洁的原因。

更新资料

请注意,您根本不需要使用jQuery来进行AJAX调用。Angular提供$http服务,使用它您将根本不会遇到该问题。您可以这样编写代码:

$scope.submitForm = function (isValid, user) {
    var regData = {
        email: user.email,
        password: user.password1
    };

    $http({
        method: "POST",
        url: "myurl",
        data: regData,          // You don't need to stringify it and no need to set any headers
    }).then(function (response) {
        // Success callback
        console.log(response.responseText);
        if (response.responseText == 'success') {
            $scope.msgalert = 'Registration Success, Proceed to Login and Continue';
        } else if (response.responseText == 'fail') {
            $scope.msgalert = 'Registration Failed, Please try again';
        }
    }, function() {
        // Error callback
    });
};
2020-07-26