控件(input、select、textarea)是用戶輸入數據的一種方式。Form(表單)是這些控件的集合,目的是將相關的控件進行分組。javascript
表單和控件提供了驗證服務,因此用戶能夠收到無效輸入的提示。這提供了更好的用戶體驗,由於用戶能夠當即獲取到反饋,知道如何修正錯誤。請記住,雖然客戶端驗證在提供良好的用戶體驗中扮演重要的角色,可是它能夠很簡單地被繞過,所以,客戶端驗證是不可信的。服務端驗證對於一個安全的應用來講仍然是必要的。css
1、Simple formhtml
理解雙向數據綁定的關鍵directive是ngModel。ngModel提供了從model到view和view到model的雙向數據綁定。而且,它還向其餘directive提供API,加強它們的行爲。java
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="SimpleForm"> <head> <meta charset="UTF-8"> <title>PropertyEvaluation</title> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body> <div ng-controller="MyCtrl" class="ng-cloak"> <form novalidate> 名字: <input ng-model="user.name" type="text"><br/> Email: <input ng-model="user.email" type="email"><br/> 性別: <input value="男" ng-model="user.gender" type="radio">男 <input value="女" ng-model="user.gender" type="radio">女 <br/> <button ng-click="reset()">還原上次保存</button> <button ng-click="update(user)">保存</button> </form> <pre>form = {{user | json}}</pre> <pre>saved = {{saved | json}}</pre> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> var app = angular.module("SimpleForm", []); app.controller("MyCtrl", function ($scope,$window) { $scope.saved = {}; $scope.update = function(user) { $scope.saved = angular.copy(user); }; $scope.reset = function() { $scope.user = angular.copy($scope.saved); }; $scope.reset(); //不合法的值將不會進入user }); </script> </body> </html>
2、Using CSS classesangularjs
爲了讓form以及控件、ngModel富有樣式,能夠增長如下class:json
下面的例子,使用CSS去顯示每一個表單控件的有效性。例子中,user.name和user.email都是必填的,但當它們修改過以後(dirty),背景將呈現紅色。這確保用戶不會直到與表單交互以後(提交以後?),發現未能知足其有效性,才爲一個錯誤而分心。api
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="CSSClasses"> <head> <meta charset="UTF-8"> <title>CSSClasses</title> <style type="text/css"> .ng-cloak { display: none; } .css-form input.ng-invalid.ng-dirty { background-color: #fa787e; } .css-form input.ng-valid.ng-dirty { background-color: #78fa89; } </style> </head> <body> <div ng-controller="MyCtrl" class="ng-cloak"> <form novalidate class="css-form" name="formName"> 名字: <input ng-model="user.name" type="text" required><br/> Email: <input ng-model="user.email" type="email" required><br/> 性別: <input value="男" ng-model="user.gender" type="radio">男 <input value="女" ng-model="user.gender" type="radio">女 <br/> <button ng-click="reset()">RESET</button> <button ng-click="update(user)">SAVE</button> </form> <pre>form = {{user | json}}</pre> <pre>saved = {{saved | json}}</pre> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> var app = angular.module("CSSClasses", []); app.controller("MyCtrl", function ($scope,$window) { $scope.saved = {}; $scope.update = function(user) { $scope.saved = angular.copy(user); }; $scope.reset = function() { $scope.user = angular.copy($scope.saved); }; $scope.reset(); //不合法的值將不會進入user }); </script> </body> </html>
3、Binding to form and control state數組
在angular中,表單是FormController的一個實例。表單實例能夠隨意地使用name屬性暴露到scope中(這裏沒看懂,scope裏面沒有一個跟form的name屬性一直的property,但因爲有「document.表單名」這種方式,因此仍是能夠獲取到的)。類似地,控件是NgModelController的實例。控件實例能夠類似地使用name屬性暴露在form中。這說明form和控件(control)二者的內部屬性對於使用標準綁定實體(standard binding primitives)綁定在視圖中的這個作法是可行的。瀏覽器
這容許咱們經過如下特性來擴展上面的例子:安全
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="ControlState"> <head> <meta charset="UTF-8"> <title>ControlState</title> <style type="text/css"> .ng-cloak { display: none; } .css-form input.ng-invalid.ng-dirty { background-color: #fa787e; } .css-form input.ng-valid.ng-dirty { background-color: #78fa89; } </style> </head> <body> <div ng-controller="MyCtrl" class="ng-cloak"> <form novalidate class="css-form" name="formName"> 名字: <input ng-model="user.name" name="userName" type="text" required><br/> <div ng-show="formName.userName.$dirty&&formName.userName.$invalid"> <span>請填寫名字</span> </div> Email: <input ng-model="user.email" name="userEmail" type="email" required><br/> <div ng-show="formName.userEmail.$dirty && formName.userEmail.$invalid">提示: <span ng-show="formName.userEmail.$error.required">請填寫Email</span> <span ng-show="formName.userEmail.$error.email">這不是一個有效的Email</span> </div> 性別: <input value="男" ng-model="user.gender" type="radio">男 <input value="女" ng-model="user.gender" type="radio">女 <br/> <input type="checkbox" ng-model="user.agree" name="userAgree" required/>我贊成: <input type="text" ng-show="user.agree" ng-model="user.agreeSign" required/> <br/> <div ng-show="!formName.userAgree || !user.agreeSign">請贊成並簽名~</div> <button ng-click="reset()" ng-disabled="isUnchanged(user)">RESET</button> <button ng-click="update(user)" ng-disabled="formName.$invalid || isUnchanged(user)">SAVE</button> </form> <pre>form = {{user | json}}</pre> <pre>saved = {{saved | json}}</pre> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> var app = angular.module("ControlState", []); app.controller("MyCtrl", function ($scope,$window) { $scope.saved = {}; $scope.update = function(user) { $scope.saved = angular.copy(user); }; $scope.reset = function() { $scope.user = angular.copy($scope.saved); }; $scope.isUnchanged = function(user) { return angular.equals(user, $scope.saved); }; $scope.reset(); //不合法的值將不會進入user }); </script> </body> </html>
4、Custom Validation
angular爲大多數公共的HTML表單域(input,text,number,url,email,radio,checkbox)類型提供了實現,也有一些爲了表單驗證的directive(required,pattern,,inlength,maxlength,min,max)。
能夠經過定義增長定製驗證函數到ngModel controller(這裏是連在一塊兒的ngModelController嗎?)中的directive來定義咱們本身的驗證插件。爲了獲得一個controller,directive以下面的例子那樣指定了依賴(directive定義對象中的require屬性)。
在下面的例子中咱們將建立兩個directive。
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="CustomValidation"> <head> <meta charset="UTF-8"> <title>CustomValidation</title> <style type="text/css"> .ng-cloak { display: none; } .css-form input.ng-invalid.ng-dirty { background-color: #fa787e; } .css-form input.ng-valid.ng-dirty { background-color: #78fa89; } </style> </head> <body> <div class="ng-cloak"> <form novalidate class="css-form" name="formName"> <div> 大小(整數 0 - 10):<input integer type="number" ng-model="size" name="size" min="0" max="10"/>{{size}}<br/> <span ng-show="formName.size.$error.integer">這不是一個有效的整數</span> <span ng-show="formName.size.$error.min || formName.size.$error.max"> 數值必須在0到10之間 </span> </div> <div> 長度(浮點數): <input type="text" ng-model="length" name="length" smart-float/> {{length}}<br/> <span ng-show="formName.length.0error.float">這不是一個有效的浮點數</span> </div> </form> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> var app = angular.module("CustomValidation", []); var INTEGER_REGEXP = /^\-?\d*$/; app.directive("integer", function () { return { require:"ngModel",//NgModelController link:function(scope,ele,attrs,ctrl) { ctrl.$parsers.unshift(function (viewValue) {//$parsers,View到Model的更新 if(INTEGER_REGEXP.test(viewValue)) { //合格放心肉 ctrl.$setValidity("integer", true); return viewValue; }else { //私宰肉…… ctrl.$setValidity("integer", false); return undefined; } }); } }; }); var FLOAT_REGEXP = /^\-?\d+(?:[.,]\d+)?$/; app.directive("smartFloat", function () { return { require:"ngModel", link:function(scope,ele,attrs,ctrl) { ctrl.$parsers.unshift(function(viewValue) { if(FLOAT_REGEXP.test(viewValue)) { ctrl.$setValidity("float", true); return parseFloat(viewValue.replace(",", ".")); }else { ctrl.$setValidity("float", false); return undefined; } }); } } }); </script> </body> </html>
5、Implementing custom form control (using ngModel)
angular實現了全部HTML的基礎控件(input,select,textarea),能勝任大多數場景。然而,若是咱們須要更加靈活,咱們能夠經過編寫一個directive來實現自定義表單控件的目的。
爲了制定控件和ngModel一塊兒工做,而且實現雙向數據綁定,它須要:
能夠查看$compileProvider.directive(http://www.cnblogs.com/lcllao/archive/2012/09/09/2677190.html)獲取更多信息。
下面的例子展現如何添加雙向數據綁定特性到能夠編輯的元素中。
<!DOCTYPE HTML> <html lang="zh-cn" ng-app="CustomControl"> <head> <meta charset="UTF-8"> <title>CustomControl</title> <style type="text/css"> .ng-cloak { display: none; } div[contenteditable] { cursor: pointer; background-color: #D0D0D0; } </style> </head> <body ng-controller="MyCtrl"> <div class="ng-cloak"> <div contenteditable="true" ng-model="content" title="點擊後編輯">My Little Dada</div> <pre>model = {{content}}</pre> <button ng-click="reset()">reset model tirgger model to view($render)</button> </div> <script src="../angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> var app = angular.module("CustomControl", []); app.controller("MyCtrl", function ($scope) { $scope.reset = function() { $scope.content = "My Little Dada"; //在這裏如何獲取NgModelController呢?若是大家知道,但願能夠指點指點!謝謝 }; }); app.directive("contenteditable", function () { return { require:"ngModel", link:function (scope, ele, attrs, ctrl) { //view -> model ele.bind("blur keyup",function() { scope.$apply(function() { console.log("setViewValue"); ctrl.$setViewValue(ele.text()); }); }); //model -> view ctrl.$render = function(value) { console.log("render"); ele.html(value); }; //讀取初始值 ctrl.$setViewValue(ele.text()); } }; }); </script> </body> </html>