AngularJs Forms詳解及簡單樣本_AngularJS

來源:互聯網
上載者:User

      控制項(input、select、textarea)是使用者輸入資料的一種方式。Form(表單)是這些控制項的集合,目的是將相關的控制項進行分組。

  表單和控制項提供了驗證服務,所以使用者可以收到無效輸入的提示。這提供了更好的使用者體驗,因為使用者可以立即擷取到反饋,知道如何修正錯誤。請記住,雖然用戶端驗證在提供良好的使用者體驗中扮演重要的角色,但是它可以很簡單地被繞過,因此,用戶端驗證是不可信的。服務端驗證對於一個安全的應用來說仍然是必要的。

一、Simple form

  理解雙向資料繫結的關鍵directive是ngModel。ngModel提供了從model到view和view到model的雙向資料繫結。並且,它還向其他directive提供API,增強它們的行為。

<!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>
 

二、Using CSS classes

  為了讓form以及控制項、ngModel富有樣式,可以增加以下class:

  1. ng-valid
  2. ng-invalid
  3. ng-pristine(從未輸入過)
  4. ng-dirty(輸入過)

  下面的例子,使用CSS去顯示每個表單控制項的有效性。例子中,user.name和user.email都是必填的,但當它們修改過之後(dirty),背景將呈現紅色。這確保使用者不會直到與表單互動之後(提交之後?),發現未能滿足其有效性,才為一個錯誤而分心。

<!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>

三、Binding to form and control state

  在angular中,表單是FormController的一個執行個體。表單一實例可以隨意地使用name屬性暴露到scope中(這裡沒看懂,scope裡面沒有一個跟form的name屬性一直的property,但由於有“document.表單名”這種方式,所以還是可以擷取到的)。相似地,控制項是NgModelController的執行個體。控制項執行個體可以相似地使用name屬性暴露在form中。這說明form和控制項(control)兩者的內部屬性對於使用標準綁定實體(standard binding primitives)綁定在視圖中的這個做法是可行的。

  這允許我們通過以下特性來擴充上面的例子:

  1. RESET按鈕僅僅在form發生改變之後才可用。
  2. SAVE按鈕僅僅在form發生改變而且輸入有效情況下可用。
  3. 為user.email和user.agree定製錯誤資訊。
<!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>

四、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屬性)。

          Model到View更新 - 無論什麼時候Model發生改變,所有在ngModelController.$formatters(當model發生改變時觸發資料有效性驗證和格式化轉換)數組中的function將排隊執行,所以在這裡的每一個function都有機會去格式化model的值,並且通過NgModelController.$setValidity(http://code.angularjs.org/1.0.2/docs/api/ng.directive:ngModel.NgModelController#$setValidity)修改控制項的驗證狀態。

          View到Model更新 - 一個相似的方式,無論任何時候,使用者與一個控制項發生互動,將會觸發NgModelController.$setViewValue。這時候輪到執行NgModelController$parsers(當控制項從DOM中取得值之後,將會執行這個數組中所有的方法,對值進行審查過濾或轉換,也進行驗證)數組中的所有方法。

  在下面的例子中我們將建立兩個directive。

       第一個是integer,它負責驗證輸入到底是不是一個有效整數。例如1.23是一個非法的值,因為它包含小數部分。注意,我們通過在數組頭部插入(unshift)來代替在尾部插入(push),這因為我們想它首先執行並使用這個控制項的值(估計這個Array是當作隊列來使用的),我們需要在轉換髮生之前執行驗證函式。

        第二個directive是smart-float。他將”1.2”和”1,2”轉換為一個合法的浮點數”1.2”。注意,我們在這不可以使用HTML5的input類型”number”,因為瀏覽器不允許使用者輸入我們預期的非法字元,如”1,2”(它只認識”1.2”)。

<!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>

五、Implementing custom form control (using ngModel)

  angular實現了所有HTML的基礎控制項(input,select,textarea),能勝任大多數情境。然而,如果我們需要更加靈活,我們可以通過編寫一個directive來實現自訂表格單控制項的目的。

  為了制定控制項和ngModel一起工作,並且實現雙向資料繫結,它需要:

實現render方法,是負責在執行完並通過所有NgModelController.$formatters方法後,呈現資料的方法。

調用$setViewValue方法,無論任何時候使用者與控制項發生互動,model需要進行響應的更新。這通常在DOM事件監聽器裡實現。
  可以查看$compileProvider.directive擷取更多資訊。

  下面的例子展示如何添加雙向資料繫結特性到可以編輯的元素中。

<!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>
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.