2015-11-19 88 views
3

我需要从我的HTML页面做了以下活动:AngularJS使用Ajax表单提交需要点击两次

  1. 用户输入电子邮件地址和密码来注册
  2. 形式发送到控制器的时候,用户点击Submit
  3. 控件使用AJAX为RESTful Server创建JSON请求,并且 服务器做出相应响应。
  4. 根据服务器的回应,用户应该在“提交”下面的当前页面(register.html)上得到警报窗口和一条 消息。 如果它是“成功 - 注册”或“失败 - 不能 注册”。

但是,目前它正在像这样工作:1),2),3)按预期工作。

  1. 用户首先用适当的消息点击Submit获取警报窗口。

  2. 用户只能点击打印的邮件SubmitAGAIN,但再次显示警报窗口。

如果我从JS删除alert('Something'),我要为消息中单击两次打印在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> 

任何想法,我该怎么办所有这些活动在一个“提交”点击?

+0

而不是'ng-show = showme',试试'ng-show = msgalert'。 – jperezov

+1

另外,你为什么要调用angular的'$ http'函数,但使用jQuery的'ajax'函数?一般来说,你需要在角度上创建一个服务(https://docs.angularjs.org/guide/services),并在你的控制器中调用_that_。 – jperezov

+0

是的,乔纳森,你是对的,我同意这一点。我的错。 – AdityaHandadi

回答

4

只是这样做:在你的控制器注入$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来获取数据并更新msgalert的$ scope变量),我们必须告诉Angular数据中的某些内容已经改变。

因此,当您从服务器获得响应并更新msgalert后,Angular不知道该更改,因为它不在Angular的上下文中,因此Angular的新摘要循环被触发并且视图未更新。

为什么你看到这是,当你再次单击表单中的提交按钮,然后在场景后面触发一个Angular的摘要循环,然后你的实际消息就会显示出来。

为了解决这个问题,我们裹着您的自定义(角范围以外)代码到使用$timeout服务,立即通知角,在msgalert值已更改

可选的角度的情况下,你可以写$scope.$apply()在你的if-else条件之后,但它会抛出一个异常,有时候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 
    }); 
}; 
+0

太棒了!这绝对有效。我读过关于http的内容,但由于某种原因,它给了我错误信息。现在我知道消息摘要的概念了,我会再次执行。谢谢! – AdityaHandadi

+0

很高兴这有帮助,你明白这一点:-) –

+0

当我试图实现$ HTTP,就像你提到的,它给了我这个错误'SyntaxError:在Object.parse意外的令牌(本地)' – AdityaHandadi

2

你的实际问题是jQuery AJAX的用法。通常,当角度$ http进行AJAX调用时,它在内部调用scope.digest循环,同时发现ajax响应。但在这里你调用jQuery的Ajax,所以棱角无法消化的变化,所以绑定不起作用。

完成方法完成之前,请尝试以下操作。

$ scope。$ apply();

如下

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

       } 
       $scope.$apply(); 
} 

但最好是使用的$ HTTP,因为它调用$范围。$适用()内。

+0

这绝对适合我。谢谢! – AdityaHandadi