详细分析使用AngularJS编程中提交表单的方式
在angularjs出现之前,很多开发者就面对了表单提交这一问题。由于提交表单的方式繁杂而不同,很容易令人疯掉……然而现在看来,依然会让人疯掉。
今天,我们会看一下过去使用php方式提交的表单,现在如何将其转换为使用angular提交。使用angular来处理表单,对我而言,是一个“啊哈”时刻(译者:表示了解或发现某事物的喜悦)。即使它甚至都没有涉及多少angular表层的东西,但是它却帮助用户看到表单提交之后的潜力,并且理解两种数据绑定方式。
我们会使用jquery平台来进行这个处理过程。所以所要做的工作首先使用javascript。我们会提交表单,展示错误信息,添加错误类,并且在javascript中显示和隐藏信息。
之后,我们会使用angular。在使用之前,我们要做大部分所需的工作,并且我们之前所做的很多工作会非常容易。让我们开始吧。
简单的表单
我们会关注两种提交表单的方式:
- 旧方法:jquery和php提交表单
- 新方法:angularjs和php提交表单
首先看一下我们的表单,超级简单:
形式要求
- 实现页面无刷新表单处理
- 输入姓名和超级英雄别名
- 如果有错误,显示错误提示
- 如果输入有误,将输入变成红色
- 如果所有内容ok,显示成功提示
文档结构
在我们的展示中,仅需两个文件
- index.html
- process.php
表单处理
让我们新建一个php来处理表单。该页面非常小并且使用post方式提交数据。
处理表单:这对我们来说并不是那么重要的。你可以使用其他你喜欢的语言来处理你的表单。
// process.php <?php $errors = array(); // array to hold validation errors $data = array(); // array to pass back data // validate the variables ====================================================== if (empty($_post['name'])) $errors['name'] = 'name is required.'; if (empty($_post['superheroalias'])) $errors['superheroalias'] = 'superhero alias is required.'; // return a response =========================================================== // response if there are errors if ( ! empty($errors)) { // if there are items in our errors array, return those errors $data['success'] = false; $data['errors'] = $errors; } else { // if there are no errors, return a message $data['success'] = true; $data['message'] = 'success!'; } // return all our data to an ajax call echo json_encode($data);
为了返回我们的数据用于ajax调用,我们需要使用echo和json_encode。这就是我们php表单处理所有需要做的操作。使用普通的jquery ajax或者angular处理表单也是这样的。
展示表单
让我们创建一个html来展示我们的表单
<!-- index.html --> <!doctype html> <html> <head> <title>angular forms</title> <!-- load bootstrap css --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load jquery --> <!-- when building an angular app, you generally do not want to use jquery --> <!-- we are breaking this rule here because jquery's $.param will help us send data to our php script so that php can recognize it --> <!-- this is jquery's only use. avoid it in angular apps and if anyone has tips on how to send data to a php script w/o jquery, please state it in the comments --> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <!-- process form with ajax (old) --> <script> <!-- we will process our form here --> </script> </head> <body> <div class="container"> <div class="col-md-6 col-md-offset-3"> <!-- page title --> <div class="page-header"> <h1><span class="glyphicon glyphicon-tower"></span> submitting forms with angular</h1> </div> <!-- show error/success messages --> <div id="messages"></div> <!-- form --> <form> <!-- name --> <div id="name-group" class="form-group"> <label>name</label> <input type="text" name="name" class="form-control" placeholder="bruce wayne"> <span class="help-block"></span> </div> <!-- superhero name --> <div id="superhero-group" class="form-group"> <label>superhero alias</label> <input type="text" name="superheroalias" class="form-control" placeholder="caped crusader"> <span class="help-block"></span> </div> <!-- submit button --> <button type="submit" class="btn btn-success btn-lg btn-block"> <span class="glyphicon glyphicon-flash"></span> submit! </button> </form> </div> </div> </body> </html>
现在,我们有了表单。我们另外还使用了bootstrap来使表单看起来不是那么丑。使用bootstrap语法规则,每个input下含有一个spot来展示我们文本的错误信息。
使用jquery提交表单
现在,让我们来使用jquery处理表单提交。我会将所有的代码添加到空的<script>标签中
<!-- index.html --> ... <!-- process form with ajax (old) --> <script> $(document).ready(function() { // process the form $('form').submit(function(event) { // remove the past errors $('#name-group').removeclass('has-error'); $('#name-group .help-block').empty(); $('#superhero-group').removeclass('has-error'); $('#superhero-group .help-block').empty(); // remove success messages $('#messages').removeclass('alert alert-success').empty(); // get the form data var formdata = { 'name' : $('input[name=name]').val(), 'superheroalias' : $('input[name=superheroalias]').val() }; // process the form $.ajax({ type : 'post', url : 'process.php', data : formdata, datatype : 'json', success : function(data) { // log data to the console so we can see console.log(data); // if validation fails // add the error class to show a red input // add the error message to the help block under the input if ( ! data.success) { if (data.errors.name) { $('#name-group').addclass('has-error'); $('#name-group .help-block').html(data.errors.name); } if (data.errors.superheroalias) { $('#superhero-group').addclass('has-error'); $('#superhero-group .help-block').html(data.errors.superheroalias); } } else { // if validation is good add success message $('#messages').addclass('alert alert-success').append('<p>' + data.message + '</p>'); } } }); // stop the form from submitting and refreshing event.preventdefault(); }); }); </script> ...
这里处理表单有不少的代码。我们有获取表单中变量的代码,有使用ajax将数据发送至我们的表单的代码,有检查是否有错和显示成功提示的代码。除此之外,我们希望每次表单提交之后,过去的错误信息都会被清除。确实是不少代码。
现在,如果表单中含有错误,则:
如果提交成功:
现在,让我们看使用angular来提交相同的表单。记住,我们不需要更改任何关于我们的php如何处理表单的内容,我们的应用依然会具备相同的功能(在同一个地方展示错误和成功信息)。
使用angular提交表单
我们准备在之前使用的<script>标签中设置我们的angular应用。所以删除里面的内容,我们就可以开始了。
设置一个angular应用
步骤为:
1. 加载angular
2. 设置module
3. 这是controller
4. 将module和controller应用于html
5. 设置双向变量绑定
6. 这是错误和信息
看起来好像是很多内容,但是最终,我们会用非常少的代码,并且看起来会非常简洁。另外,创建带有更多输入更大的表单,也会更容易。
angular 组件和控制器
首先,加载angular并且新建组件和控制器
<!-- index.html --> ... <!-- load jquery --> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <!-- load angular --> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script> <!-- process form with ajax (new) --> <script> // define angular module/app var formapp = angular.module('formapp', []); // create angular controller and pass in $scope and $http function formcontroller($scope, $http) { } </script> </head> <!-- apply the module and controller to our body so angular is applied to that --> <body ng-app="formapp" ng-controller="formcontroller"> ...
现在,我们有了angular应用的基础。我们已经加载了angular,创建了组件模块和控制器,并且将其应用于我们的网站。
接下来,我将展示双向绑定是如何工作的。
双向数据绑定
这是angular的核心思想之一,也是功能最强大的内容之一。在angular文档中,我们看到:“在angular网页应用中的数据绑定,是模型和视图层之间的数据自动同步。”这意味着,我们需要在表单中抓取数据,使用$('input[name=name]').val()并不是必需的。
我们在angular中将数据和变量绑定在一起,无论是javascript也好,view也罢,只要有改变,两者皆变。
为了演示数据绑定,我们需要获取表单的input来自动填充变量formdata。让我们回到应用于页面的angular控制器中。我们在过一下$scope和$http。
$scope:控制器和视图层之间的粘合剂。基本上,变量使用$scope从我们的控制器和视图层之间传递和往来。具体详细的定义,请参见文档。
$http:angular服务来帮助我们处理post请求。更多信息,请参见文档。
使用数据绑定获取变量
好了,闲话少说。我们将这些讨论应用到表单中去。方法比上面讨论的要简单。我们想angular控制器和视图中分别添加一行。
<!-- index.html --> ... <!-- process form with ajax (new) --> <script> // define angular module/app var formapp = angular.module('formapp', []); // create angular controller and pass in $scope and $http function formcontroller($scope, $http) { // create a blank object to hold our form information // $scope will allow this to pass between controller and view $scope.formdata = {}; } ...
现在,我们已经建立了一个formdata对象。让我们用表单数据来填充它。在显示调用每个输入和获得val()之前,我们用ng-model绑定一个特殊的输入到变量。
<!-- index.html --> ... <!-- form --> <form> <!-- name --> <div id="name-group" class="form-group"> <label>name</label> <input type="text" name="name" class="form-control" placeholder="bruce wayne" ng-model="formdata.name"> <span class="help-block"></span> </div> <!-- superhero name --> <div id="superhero-group" class="form-group"> <label>superhero alias</label> <input type="text" name="superheroalias" class="form-control" placeholder="caped crusader" ng-model="formdata.superheroalias"> <span class="help-block"></span> </div> <!-- submit button --> <button type="submit" class="btn btn-success btn-lg btn-block"> <span class="glyphicon glyphicon-flash"></span> submit! </button> </form> <!-- show data from inputs as they are being typed --> <pre> {{ formdata }} </pre> ...
现在,既然angular已经将每个输入绑到了formdata。 当你输入每个输入框,你可以看到formdata对象被填充了!有没有很酷!
你不必在view中使用$scope。一切被认为是嵌入到$scope中的。
处理表单
在我们的旧表单中,我们使用jquery提交表单,像这样$('form').submit()。现在我们使用angular称作ng-submit的特性。要想完成这个,我们需要添加一个控制器函数来处理表单,然后告诉我们form使用这个控制器函数:
<!-- index.html --> ... <!-- process form with ajax (new) --> <script> // define angular module/app var formapp = angular.module('formapp', []); // create angular controller and pass in $scope and $http function formcontroller($scope, $http) { // create a blank object to hold our form information // $scope will allow this to pass between controller and view $scope.formdata = {}; // process the form $scope.processform = function() { }; } ... <!-- form --> <form ng-submit="processform()"> ...
现在我们的form知道提交时使用控制器函数了。既然已经到位了,然我们用$http来处理表单吧。
处理表单的语法看起来跟原始方式很像。好处是我们不需要手动抓取表单数据,或者注入,隐藏,添加类显示错误或成功信息。
<!-- index.html --> ... // process the form $scope.processform = function() { $http({ method : 'post', url : 'process.php', data : $.param($scope.formdata), // pass in data as strings headers : { 'content-type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload) }) .success(function(data) { console.log(data); if (!data.success) { // if not successful, bind errors to error variables $scope.errorname = data.errors.name; $scope.errorsuperhero = data.errors.superheroalias; } else { // if successful, bind success message to message $scope.message = data.message; } }); }; ...
这就是我们的表单!没有添加或移除类。我们需要每次提交表单时都清楚错误。我们只需绑定变量和需要用到的视图。这非常棒,因为处理器用来处理数据,而视图用来显示数据.
jquery post vs angular post
有时能看到用post方式提交在服务器中看不到数据,这是因为jquery和angular的序列化和发送数据的方式不同。这归结于你所使用的服务器语言和它理解angular提交的数据的能力。
上面的代码是应用于php服务器的,jquery对于$.param函数则是必需的。虽然实现上文中提到的内容有非常多不使用jquery的方法,但在本实例中,使用jquery的唯一原因就是,它更简单。
下面简洁的语法将会基于你服务器端语言来工作。
简洁语法
这个例子是以字符串的方式发送数据,并且发送你的头信息。如果你不需要这些,并且希望angular 的$http post尽可能的简洁,我们可以使用简写方法:
... $http.post('process.php', $scope.formdata) .success(function(data) { ... }); ...
绝对更简洁更容易记住方法。
$http 内部控制器: 理想的,你可以将$http请求从controller移除到 service.这只是为了演示目的,我们将会尽快在service上进行讨论.
在视图中显示错误和信息
我们将使用指令ng-show和ng-class来处理我们的视图,angular双方括号允许我们将变量放置在我们需要的地方。
- ng-show: 根据变量值是否存在来显示或隐藏元素. 文档
- ng-class: 根据变量值是否存在(或一些其他表达式)来添加或移除类. 文档
<!-- index.html --> ... <!-- show error/success messages --> <div id="messages" ng-show="message">{{ message }}</div> <!-- form --> <form> <!-- name --> <div id="name-group" class="form-group" ng-class="{ 'has-error' : errorname }"> <label>name</label> <input type="text" name="name" class="form-control" placeholder="bruce wayne"> <span class="help-block" ng-show="errorname">{{ errorname }}</span> </div> <!-- superhero name --> <div id="superhero-group" class="form-group" ng-class="{ 'has-error' : errorsuperhero }"> <label>superhero alias</label> <input type="text" name="superheroalias" class="form-control" placeholder="caped crusader"> <span class="help-block" ng-show="errorsuperhero">{{ errorsuperhero }}</span> </div> ...
我们的表单完成了!通过强大的angular,我们可以将这些愚蠢的显示/隐藏的js代码逻辑从视图中移走 了。现在我们的js文件只用来处理数据,并且视图可以做它自己的事情了。
我们的类和错误/成功等提示信息将在可获取时显示而不可获取时隐藏。当我们无须再像使用老的javascript那样担心是否已经考虑全面,这变得更加容易。你也无须再担心是否记得隐藏每处form提交时的那些错误信息。
angular表单验证 获取更多表单验证的信息,请研读我们另一文章:angularjs form validation。
结束语
现在我们已把美观的表单全部转变为angular的了。我们共同学习了许多概念,希望你与它们接触更多,它们也将更易用。
回顾:
- 创建一个angular module
- 创建一个angular controller
- 双向数据绑定
- ng-model绑定inputs
- ng-click提交表单
- 使用双向数据绑定展示表单错误
- 展示一个基于是否变量存在的div
- 添加一个基于是否变量存在的类
这些angular技术将在更庞大的应用中使用,你可以用它们创建许多好东西。祝angular之途愉快,敬请期待更多深入的文章。同时,你也可以通过深入了解其指南,服务和厂商等来继续学习angular。
上一篇: 卤水是什么?其实它在你生活中很常见
下一篇: 以前的学生长大了,做了设计师