AngularJS表单
AngularJS表单处理简介
AngularJS具有一些功能,可将HTML表单输入字段的数据绑定到模型对象($ scope)。这些功能使使用表单变得更加容易。
我们可以使用ng-model指令将输入字段绑定到模型属性,如下所示:
<input type="text" id="firstName" ng-model="myForm.firstName">
这种绑定是双向的,这意味着如果$ scope.myForm.firstName在相应的控制器函数中设置了一个值,则输入字段将从该值开始。另外,一旦用户在文本字段中键入内容,该值将从文本字段复制到$ scope.myForm.firstName属性中。
这是我们可以使用的完整AngularJS表单示例:
<!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script> </head> <body ng-app="myapp"> <div ng-controller="MyController" > <form> <input type="text" name="firstName" ng-model="myForm.firstName"> First name <br/> <input type="text" name="lastName" ng-model="myForm.lastName"> Last name <br/> </form> <div> {{myForm.firstName}} {{myForm.lastName}} </div> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope) { $scope.myForm = {}; $scope.myForm.firstName = "Jakob"; $scope.myForm.lastName = "Jenkov"; } ); </script> </body> </html>
本示例将表单中的两个输入字段绑定到$ scope.myForm.firstName和$ scope.myForm.lastName属性。这两个属性都在控制器功能中设置了一个值。首次呈现页面时,这些值将显示在输入字段中。当用户在文本字段中输入内容时,它也会被复制到这些属性中。
该示例还包含两个插值指令({{}}
)。这两个指令将在表单字段下方插入" myForm.firstName"和" myForm.lastName"的值。当我们在文本框中输入内容时,它将被复制到myForm.firstName
和myForm.lastName
属性中。从那里将通过两个插值指令将其插入HTML。当用户在表单字段中输入数据时会发生这种数据绑定,因此插值指令将在键入时更新值(这看起来很酷,但我不记得我上一次在Web应用程序表单中实际需要它的时间)。
绑定复选框
如果将复选框(<input type =" checkbox">)绑定到模型属性,则如果选中该复选框,则模型属性将设置为
true,否则为
false`。
如果我们需要其他值而不是在模型中插入" true"和" false",则可以使用" ng-true-value"和" ng-false-value"指令,如下所示:
<input type="checkbox" ng-model="myForm.wantNewsletter" ng-true-value="yes" ng-false-value="no" >
绑定单选按钮
单选按钮也很容易绑定到模型属性。如果我们有一组单选按钮,只需将它们全部绑定到同一模型属性。选中的单选按钮会将其值复制到模型属性中。这是一个例子:
<input type="radio" ng-model="myForm.whichNewsletter" value="weeklyNews"> <input type="radio" ng-model="myForm.whichNewsletter" value="monthlyNews">
绑定选择框
将"选择"框绑定到模型属性也相当简单。这是一个例子:
<div ng-controller="MyController" > <form> <select ng-model="myForm.car"> <option value="nissan">Nissan</option> <option value="toyota">Toyota</option> <option value="fiat">Fiat</option> </select> </form> <div> {{myForm.car}} </div> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope) { $scope.myForm = {}; $scope.myForm.car = "nissan"; } ); </script>
ng-options
除了使用静态HTML选项,我们还可以让AngularJS根据$ scope对象中的数据创建option元素。我们可以通过在select元素内使用ng-options指令来实现。这是一个例子:
<div ng-controller="MyController" > <form> <select ng-model="myForm.car" ng-options="obj.id as obj.name for obj in myForm.options"> </select> </form> <div> {{myForm.car}} </div> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope) { $scope.myForm = {}; $scope.myForm.car = "nissan"; $scope.myForm.options = [ { id : "nissan", name: "Nissan" } ,{ id : "toyota", name: "Toyota" } ,{ id : "fiat" , name: "Fiat" } ]; } ); </script>
ng-options指令遵循以下格式:
optionBinding expression dataSource expression
dataSource expression专门说明$ scope对象中的哪些数据将用作option元素的数据源。在上面的示例中," dataSource expression"就是这一部分:
for obj in myForm.options
它将obj定义为myForm.options数组中的每个对象。因此,将从$ scope对象中myForm.options数组中的每个元素生成一个option元素。
" optionBinding expression"指定将哪些属性用作" value"并为每个" option"元素添加标签。在上面的示例中," optionBinding"是这一部分:
obj.id as obj.name
这将每个对象的obj.id属性定义为所生成的每个option元素的value,并将obj.name属性定义为标签。如果要让"值"和标签来自同一属性,只需忽略" as obj.name"部分(表达式的标签部分)。
我们可以在optionBinding expression
和dataSource expression
内部调用$ scope对象上的函数。这是一个例子:
obj.id as getLabelName(obj) for obj in getOptionArray()
本示例将使用getLabelName(obj)函数调用返回的值作为标签,并迭代getOptionArray()函数调用返回的对象。
我们可以通过在" optionBinding"表达式中添加" group by"部分来创建选项组(" <optgroup>" HTML元素,其中包含" option"元素)。这是一个例子:
obj.id as obj.name group by obj.type
本示例将使用obj.type属性将生成的option元素分组为optgroup元素,以确定将哪些option元素分组在一起。在obj.type属性中具有相同值的对象将被分组到相同的optgroup元素中。
我们还可以迭代对象的属性,而不是迭代对象的数组。这是一个例子:
propName as propValue for (propName, propValue) in objectWithProperties
本示例将把$ scope.objectWithProperties对象中所有属性的属性名称绑定为option选项元素value并将属性值绑定为标签。
空选项
如果控制器功能在$ scope对象中为选择框设置的值与任何option元素的value属性都不匹配,则AngularJS在选择框中插入一个空的option元素。
我们可以通过在HTML中插入option
元素来为此空的option
元素设置标签,如下所示:
<form> <select ng-model="myForm.car" ng-options="obj.id as obj.name for obj in myForm.options"> <option value="">Please choose a car</option> </select> </form>
选择多个选项
如果需要使用户能够选择多个选项的选择框,则需要在<select>
元素内插入multiple =" true"
属性。
启用多选项选择后,数据绑定将更改。现在不再将<select>元素绑定到单个字符串值,而是将其绑定到值数组。因此,我们还可以使用数组设置选定的值。这是显示此的示例:
<div ng-controller="MyController" > <form> <select multiple="true" ng-model="myForm.car" ng-options="obj.id as obj.name for obj in myForm.options"> </select> </form> <div> {{myForm.car}} </div> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope) { $scope.myForm = {}; $scope.myForm.car = ["nissan"]; $scope.myForm.options = [ { id : "nissan", name: "Nissan" } ,{ id : "toyota", name: "Toyota" } ,{ id : "fiat" , name: "Fiat" } ]; } ); </script>
表格验证
AngularJS有一组可以使用的表单验证指令。 AngularJS会在将表单字段的值复制到绑定表单字段的$ scope属性中之前对其进行验证。如果表单字段无效,则其值不会复制到绑定的$ scope
属性中。而是清除了相应的$ scope属性。这样做是为了防止$ scope
属性包含无效值。
以下各节介绍了每种格式验证指令。
ng-最小长度+ ng-最大长度
ng-minlength和ng-maxlength表单验证指令可用于验证在表单字段中输入的数据长度。这是一个例子:
<div ng-controller="MyController" > <form> <input type="text" id="name" ng-model="myForm.name" ng-minlength="5" ng-maxlength="12"> Name <br/> </form> <div> {{myForm.name}} </div> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope) { $scope.myForm = {}; $scope.myForm.name = "Jakob Jenkov"; } ); </script>
本示例将ng-minglength设置为5,将ng-maxlength设置为12. 这意味着,如果输入字段中的文本少于5个字符或者超过12个字符长,则输入字段中的值不会复制到$ scope.myForm.name属性中。我们可以自己尝试该示例,然后看看会发生什么。
注意div
元素,它显示$ scope.myForm.name
的值。这将向我们显示从文本字段复制到$ scope.myForm.name属性的值。请注意,当文本字段包含少于5个或者超过12个字符时,该字段为空。
ng模式
ng-pattern指令可用于根据正则表达式验证输入字段的值。这是一个例子:
<input type="text" id="name" ng-model="myForm.name" ng-pattern="/^\d+$/"> Name <br/>
正则表达式必须遵循JavaScript正则表达式语法。本示例定义一个正则表达式,该正则表达式与包含至少1个数字的数字字符串匹配。
ng必需
ng-required指令检查form字段的值是否为空。实际上,我们仅使用HTML5的" required"属性,AngularJS会自动检测到它。
检查字段验证状态
如果给<form>元素一个name属性,则该表单将作为属性添加到$ scope对象中。这是一个例子:
<form name="myFormNg" ng-submit="myForm.submitTheForm()" > ... </form>
当我们在$ scope对象上调用一个函数(控制器函数添加到$ scope对象中的函数)时,可以通过其名称访问ngFormController对象,如下所示:
$scope.myFormNg
如果我们在表单内的表单字段中添加" name"属性,则可以将其" ngModelController"对象作为其" ngFormController"对象上的属性进行访问。这是一个例子:
<form name="myFormNg" ng-submit="myForm.submitTheForm()" > <input name="firstName" type="text" ng-model="myForm.firstName"> </form>
我们现在可以像这样访问"名字"输入字段的" ngModelController":
$scope.myFormNg.firstName
ngFormController和ngModelController对象都包含一组属性,用于判断表单或者输入字段是否有效。这些属性是:
属性 | 描述 |
$ pristine | |
$ dirty | $ pristine`的反义-如果表单未更改,则为false-如果表单未被更改,则为true。 |
$ valid | 如果表单字段(或者整个表单=所有表单字段)有效,则为真。否则为假。 |
$ invalid | 与$ valid`相反-如果该字段(或者表单中的所有字段)有效,则为false;如果该字段(或者for中的单个字段)无效,则为true。 |
我们可以使用这些属性在输入字段上设置匹配的CSS类。这是一个例子:
<style> .fieldValid { border: 1px solid #00ff00; } .fieldInvalid { border: 1px solid #ff0000; } </style> <div ng-controller="MyController" > <form name="myFormNg" > <input type="text" ng-class="myForm.getFormFieldCssClass(myFormNg.name)" id="name" name="name" ng-model="myForm.name" ng-minlength="2"> Name <br/> </form> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope, $http) { $scope.myForm = {}; $scope.myForm.getFormFieldCssClass = function(ngModelController) { //console.log("getting css class: " + ngModelController.$valid) ; if(ngModelController.$pristine) return ""; return ngModelController.$valid ? "fieldValid" : "fieldInvalid"; } } ); </script>
注意在input字段上的ng-class指令。该指令使用myFormNg.name作为参数调用myForm.getFormFieldCssClass()函数。这是"名称"输入元素的" ngModelController"。 myForm.getFormFieldCssClass()只是将匹配的CSS类作为字符串返回。
我们也可以使用验证属性显示或者隐藏带有验证消息的div
元素。这是以前的表格,添加了div
:
<div ng-controller="MyController" > <form name="myFormNg" ng-submit="myForm.submitTheForm()" novalidate> <input type="text" ng-class="myForm.getFormFieldCssClass(myFormNg.name)" id="name" name="name" ng-model="myForm.name" ng-minlength="2"> Name <br/> <div ng-show="myFormNg.name.$invalid"> You must enter a valid name. </div> </form> </div>
注意div
元素上的ng-show
指令。该指令使用myFormNg.name。$ invalid验证属性的值来确定是否应显示div。
请记住,我们也可以访问ngFormController的$ pristine,$ dirty,$ valid和$ invalid属性。这些属性包含整个表单的验证状态。如果表单无效,此按钮代码示例将禁用"提交"按钮:
<button ng-disabled="myFormNg.$invalid">Submit Form</button>
提交表格
我们可以通过两种方式提交表单:
- 使用具有ng-click属性的
button
元素。 - 在form元素上使用ng-submit属性(伪指令)。
在这两种情况下,都会在$ scope对象上调用JavaScript函数。我们可以将此JavaScript函数添加到控制器函数中的$ scope对象。 JavaScript函数应该通过AJAX将数据从表单发送到服务器。
这是在按钮元素上使用ng-click属性的形式:
<div ng-controller="MyController" > <form> <input type="text" id="name" ng-model="myForm.name" ng-minlength="5" ng-maxlength="12"> Name <br/> <select ng-model="myForm.car"> <option value="nissan">Nissan</option> <option value="toyota">Toyota</option> <option value="fiat">Fiat</option> </select> <button ng-click="myForm.submitTheForm()">Submit Form</button> </form> <div> {{myForm.name}} </div> <div> {{myForm.car}} </div> </div> <script> angular.module("myapp", []) .controller("MyController", function($scope, $http) { $scope.myForm = {}; $scope.myForm.name = "Jakob Jenkov"; $scope.myForm.car = "nissan"; $scope.myForm.submitTheForm = function(item, event) { console.log("--> Submitting form"); var dataObject = { name : $scope.myForm.name ,car : $scope.myForm.car }; var responsePromise = $http.post("/angularjs-examples/json-test-data.jsp", dataObject, {}); responsePromise.success(function(dataFromServer, status, headers, config) { console.log(dataFromServer.title); }); responsePromise.error(function(data, status, headers, config) { alert("Submitting form failed!"); }); } }); </script>
注意ng-click属性是如何指向myForm.submitTheForm()函数的,并注意submitTheForm()函数是如何添加到控制器函数内的$ scope对象的。
这是使用ng-submit
属性提交表单的同一表单:
<form ng-submit="myForm.submitTheForm()"> <input type="text" id="name" ng-model="myForm.name" ng-minlength="5" ng-maxlength="12"> Name <br/> <select ng-model="myForm.car"> <option value="nissan">Nissan</option> <option value="toyota">Toyota</option> <option value="fiat">Fiat</option> </select> <input type="submit" value="Submit Form"> </form>
如我们所见,这两种机制非常相似。他们都在$ scope对象上调用了一个commit函数。