學習筆記-AngularJs(八)


在使用form.FormController和ngModel.NgModelController之前,先來學習一下怎么一個ng-model-options指令,覺得怎么這個指令挺好用的,我們知道ng-model是可以實現數據的雙向綁定,至於雙向數據綁定這個概念時必須要清楚的,都是這樣的一個過程,view->scope和scope->view,只要雙向綁定的element都是走怎么一個過程的,那么這個ng-model-options,就是可以實現對延遲更新、如何觸發更新、時區(timezone針對input[type='date']等)等的控制,來看一下官網(http://t.cn/RUbL4rP這個不是,哈哈)的例子:

//github上的block-example/表單操作-11/ng-model-options.html
angular.module('optionsExample', []) .controller('ExampleController', ['$scope', function($scope) { $scope.user = { name: 'say', data: '' }; $scope.cancel = function(e) { if (e.keyCode == 27) { $scope.userForm.userName.$rollbackViewValue(); } }; }]);
<div ng-controller="ExampleController">
  <form name="userForm">
    Name:
    <input type="text" name="userName"
           ng-model="user.name"
           ng-model-options="{ updateOn: 'blur',debounce: 1000 ,getterSetter: false  }"
           ng-keyup="cancel($event)" /><br />

    Other data:
    <input type="text" ng-model="user.data" /><br />
  </form>
  <pre>user.name = <span ng-bind="user.name"></span></pre>
</div>

updateOn:可以寫入事件名字,將此element按所寫事件觸發更新

debounce:當我們寫進keydowm事件的時候,我需要的是它盡可能說是當我輸入完畢后,再去觸發更新,那么這個時候我們可以延遲個1s!

getterSetter:為true的時候,則是指element的值是從函數return過來滴!

我們看一下這里, $scope.userForm.userName.$rollbackViewValue(); userForm、userName是什么鬼?眼尖的可以看到是表單的name和input[name='userName'],那么其實可以怎么理解表單實例可以隨意地使用name屬性暴露到scope中,於是在$scope就可以使用表單實例了,便可以使用表單控制器的屬性和方法了!

form.FormController是啥?

FormController跟蹤所有input和form的各種狀態的控制,如被有效/無效/已交互/未交互。官網文檔:http://docs.angularjs.cn/api/ng/type/form.FormController

其擁有的方法:

$rollbackViewValue(); $commitViewValue(); $addControl(); $removeControl(); $setValidity(); $setDirty(); $setPristine(); $setUntouched(); $setSubmitted();

$addControl()  //添加ngModel controller ,ngModel會自動添加,除非自定義指令或許會用上
$removeControl()  //與$addControl()相反
$setValidity()  //在自定義表單檢驗有着很大作用

$rollbackViewValue() //這個我是這樣理解的,回滾到上一個ViewValue

擁有的屬性:

$pristine(form沒被動過)  $dirty(form被動過) $valid(全部驗證通過) $invalid(驗證不通過) $submitted

$error
    email、max、maxlength、min、minlength、number、pattern、required、url、date、datetimelocal、time、week、month

給一個官網的例子(使用表單控制器的屬性和方法怎么去驗證input的正確性):

 
         
//github上的block-example/表單操作-11/ng-form.html,其它類型的input[type=*]驗證也都更新到github了
<!doctype html>
<html ng-app='formExample'>
    <head>
        <meta charset="utf8"/>
        <script src="http://code.angularjs.org/angular-1.0.1.min.js"></script>
        <style>
         .my-form {
           -webkit-transition:all linear 0.5s;
           transition:all linear 0.5s;
           background: transparent;
         }
         .my-form.ng-invalid {
           background: red;
         }
        </style>
        <script>
          angular.module('formExample', [])
            .controller('FormController', ['$scope', function($scope) {
              $scope.userType = 'guest';
              $scope.email = '739288994@qq.com';

              var list = $scope.list = [];

              $scope.submit = function() {
                     if($scope.userType){ list.push(this.userType);}
                     if($scope.email){  list.push(this.email);}    
                      // console.log(this.userType+","+this.email);
                      // console.log($scope.list);
                  };
            }]);
        </script>
    </head>
    <body>    
        <!--表單控制器-->
        <form name="myForm" ng-submit="submit()"  ng-controller="FormController" class="my-form" >
          userType: <input name="input" type="text" ng-model="userType" required>
          <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>  <!--這里的意思是沒有填的話就會顯示-->
          email:  <input name="email" type="email"  ng-model="email">
                <span class="error" ng-show="myForm.email.$error.email">Wrong Email!</span>
          <br> 
          <input type="submit" value="提交" id="submit" />
          <tt>userType = {{userType}}</tt><br>
          <tt>email = {{email}}</tt><br>
          <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br> <!--表單的input的有效為true-->
          <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br> <!--表單的input的$error-->
          <tt>myForm.email.$valid = {{myForm.email.$valid}}</tt><br> <!--表單的input的有效為true-->
          <tt>myForm.email.$error = {{myForm.email.$error}}</tt><br> <!--表單的input的$error-->
          <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br> 
          <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>  <!--$error屬性的required-->
          <tt>myForm.$valid = {{myForm.$valid}}</tt><br>        <!--有效效為true-->
          <tt>myForm.$invalid = {{myForm.$invalid}}</tt><br>    <!--無效為true-->
          <tt>myForm.$pristine= {{myForm.$pristine}}</tt><br>   <!--與表單有相互作用為true-->
          <tt>myForm.$dirty= {{myForm.$dirty}}</tt><br>   <!--與表單無相互作用為true-->
          <tt>myForm.$submitted = {{myForm.$submitted}}</tt><br>   
          <tt>提交的數據:{{list|json}}</tt>
         </form>
    </body>
</html>

<!-- If the name attribute is specified, the form controller is published onto the current scope under this name. -->

<!--表單阻止了表單默認action提交的方式,改用ng-submit或ng-click對表單進行綁定,具體操作看列子-->

<!-- <form [name=""]>...</form> 等價於 <div ng-form='##'></div> 控制器為name屬性的值 -->

具體可以看代碼!

ngModel.NgModelController是啥?

NgModelController 為ngModel指令提供了API。該控制器包含數據雙向綁定服務、驗證、Value格式化和解析、CSS更新。它不包含任何邏輯處理DOM渲染或DOM event,這樣的DOM相關邏輯應使用其他指令,NgModelController用來控制元素的數據綁定。Angular默認提供許多關於input元素 DOM邏輯處理。官網文檔:http://docs.angularjs.cn/api/ng/type/ngModel.NgModelController

其擁有的方法:

$render(); $isEmpty(value); $setValidity(validationErrorKey, isValid); $setPristine(); $setDirty(); $setUntouched(); $setTouched(); $rollbackViewValue(); $validate(); $commitViewValue(); $setViewValue(value, trigger);

$render: angular 會把 $modelValue 經過 $formatters 得出來的值放入 $viewValue中,(這時 $viewValue = $modelValue 經過 $formatters) 然后觸發我們寫好的 $render . 跟着$setViewValue(value, trigger);一起使用。

$setViewValue:scope改變$modelValue,使用$setViewValue(),改變$viewValue

$setValidity:使用這個配合$parsers可以實現表單自定義驗證

擁有的屬性:

$viewValue  //界面顯示的數據

$modelValue //$scope上面的value

$parsers //在
view->model的時候會觸發的一個函數組,無論什么時候Model發生改變,所有的ngModelController.$formatters(model發生改變時觸發數據有效驗證和格式化轉變)數組中的function將排隊執行,所以在這里每一個function都有機會去格式化model的值,並且通過NgModelController.$setValidity修改空間的驗證狀態。


$formatters //
model->view的時候會觸發的一個函數組, 無論任何時候用戶與控件發生交互,將會觸發NgModelCtroller.$setViewValue。這時候輪到執行NgModelController.$parsers(當控件從dom取值之后,將會執行這個數組中的所有方法,對值進行審查過濾或轉換,也進行驗證)數組中的所有方法。


$validators
$asyncValidators
$viewChangeListeners
$error
$pending
$untouched
$touched
$pristine
$dirty
$valid
$invalid
$name

 那么多個屬性都差不多,是不是關系很密切勒!雙向綁定的機制可以在$parsers和$formatters可以體現出來,通過這些我們可以在view->scope做類似表單驗證(自定義)的功能(配合$setValidity(validationErrorKey, isValid);),scope->view數據格式自定義等操作(配合$setViewValue(value, trigger);),可以看一下下面的這個例子(https://github.com/xiaobin5201314/AngularJS-Learning/blob/master/block-example/表單操作-11/ng-model.html):

 

 
         

var custom = angular.module('customControl', ['ngSanitize']);

custom.directive("noxiaobin", function () {
return {
restrict: "A",
require: "?ngModel",
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.push(function (v) { //傳說中的驗證器

if (v != "xiaobin") {
ngModel.$setValidity('noxiaobin', true); //通過獲取從dom過來的值,然后進行驗證,使用$setValidity('noxiaobin', true);改變noxiaobin的值,然后反饋會dom
return v;
} else {
ngModel.$setValidity('noxiaobin', false);
return undefined;
}

});
}
}
});

 
         

custom.directive('contenteditable', ['$sce', function($sce) {
return {
restrict: 'A', //指定該指令是為屬性類型的指令
require: '?ngModel', // 與ngModel指令的相互交流
link: function(scope, element, attrs, ngModel) { //scope分別是指令作用的作用域,element觸發指令的元素,attrs是element的屬性集合,ngmodel是控制器就是引入的ngModel
if (!ngModel) return;

 
         

// output data to the view
ngModel.$render = function() {
element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); //$viewValue的值進行format
};

 
         

//對element的監聽
element.on('blur keyup change', function() {
scope.$evalAsync(read); //執行read方法
});
read(); // 初始化

 
         

// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if ( attrs.stripBr && html == '<br>' ) {
html = '';
}

 
         

ngModel.$setViewValue(html); //獲取ViewValue,設置$viewValue
}

}
};
}]);

 
    <form name="myForm">
         <div contenteditable 
              name="myWidget" ng-model="userContent"
              strip-br="true"
              required>點擊編輯</div>
          <span ng-show="myForm.myWidget.$error.required">Required!</span>

          <input type="text" name="email" ng-model="email" noxiaobin />
          <span ng-show="myForm.email.$error.noxiaobin">Value nerver have xiaobin!</span>
         <hr>
         <textarea ng-model="userContent"></textarea>
    </form>

 以上有兩個指令分別是

1、view->scope,配合$setValidity(validationErrorKey, isValid);進行表單驗證,通過反饋回view的noxiaobin來判斷是否顯示

2、scope->view,使用$setViewValue(value, trigger);設置view的值,然后觸發$render,對其進行格式化

3、代碼下載:https://github.com/xiaobin5201314/AngularJS-Learning

對於ngModel.NgModelController確實有些繞,也有些地方還是不懂,不過也有些文章寫得還是比較明晰的,如:http://sentsin.com/web/659.html,如果對ngModel.NgModelController有那些更加全,或是更加詳細的資料可以拿給我學習學習!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM