AngularJS表单

时间:2020-01-09 10:34:01  来源:igfitidea点击:

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.firstNamemyForm.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 expressiondataSource 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>

选择多个选项

如果需要使用户能够选择多个选项的选择框,则需要在&lt;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函数。