AngularJs學習筆記--Forms

1、Simple formjavascript

  理解雙向數據綁定的關鍵directivengModelngModel提供了從modelviewviewmodel的雙向數據綁定。而且,它還向其餘directive提供API,加強它們的行爲。css

<!DOCTYPE HTML>
<html 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">
    <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 classeshtml

  爲了讓form以及控件、ngModel富有樣式,能夠增長如下classjava

  • ng-validangularjs

  • ng-invalidjson

  • ng-pristine(從未輸入過)api

  • ng-dirty(輸入過)數組

  下面的例子,使用CSS去顯示每一個表單控件的有效性。例子中,user.nameuser.email都是必填的,但當它們修改過以後(dirty),背景將呈現紅色。這確保用戶不會直到與表單交互以後(提交以後?),發現未能知足其有效性,才爲一個錯誤而分心。瀏覽器

<!DOCTYPE HTML>
<html 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">
    <form novalidate 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 stateapp

  在angular中,表單是FormController的一個實例。表單實例能夠隨意地使用name屬性暴露到scope中(這裏沒看懂,scope裏面沒有一個跟formname屬性一直的property,但因爲有「document.表單名」這種方式,因此仍是能夠獲取到的)。類似地,控件是NgModelController的實例。控件實例能夠類似地使用name屬性暴露在form中。這說明form和控件(control)二者的內部屬性對於使用標準綁定實體(standard binding primitives)綁定在視圖中的這個作法是可行的。

  這容許咱們經過如下特性來擴展上面的例子:

  • RESET按鈕僅僅在form發生改變以後纔可用。

  • SAVE按鈕僅僅在form發生改變並且輸入有效的狀況下可用。

  • user.emailuser.agree定製錯誤信息。

<!DOCTYPE HTML>
<html 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">
    <form novalidate 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表單域(inputtext,number,url,email,radio,checkbox)類型提供了實現,也有一些爲了表單驗證的directiverequiredpattern,inlengthmaxlengthminmax)。

  能夠經過定義增長定製驗證函數到ngModel controller(這裏是連在一塊兒的ngModelController嗎?)中的directive來定義咱們本身的驗證插件。爲了獲得一個controllerdirective以下面的例子那樣指定了依賴(directive定義對象中的require屬性)。

  • ModelView更新 不管何時Model發生改變,全部在ngModelController.$formatters(當model發生改變時觸發數據有效性驗證和格式化轉換)數組中的function將排隊執行,因此在這裏的每個function都有機會去格式化model的值,而且經過NgModelController.$setValidityhttp://code.angularjs.org/1.0.2/docs/api/ng.directive:ngModel.NgModelController#$setValidity)修改控件的驗證狀態。

  • ViewModel更新 一個類似的方式,不管任什麼時候候,用戶與一個控件發生交互,將會觸發NgModelController.$setViewValue。這時候輪到執行NgModelController$parsers(當控件從DOM中取得值以後,將會執行這個數組中全部的方法,對值進行審查過濾或轉換,也進行驗證)數組中的全部方法。

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

  • 第一個是integer,它負責驗證輸入究竟是不是一個有效的整數。例如1.23是一個非法的值,由於它包含小數部分。注意,咱們經過在數組頭部插入(unshift)來代替在尾部插入(push),這由於咱們想它首先執行並使用這個控件的值(估計這個Array是看成隊列來使用的),咱們須要在轉換髮生以前執行驗證函數。

  • 第二個directivesmart-float。他將」1.2」和」1,2」轉換爲一個合法的浮點數」1.2」。注意,咱們在這不可使用HTML5input類型」number」,由於瀏覽器不容許用戶輸入咱們預期的非法字符,如」1,2」(它只認識」1.2」)。

<!DOCTYPE HTML>
<html 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>
    <form novalidate 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的基礎控件(inputselecttextarea),能勝任大多數場景。然而,若是咱們須要更加靈活,咱們能夠經過編寫一個directive來實現自定義表單控件的目的。

  爲了制定控件和ngModel一塊兒工做,而且實現雙向數據綁定,它須要:

  • 實現render方法,是負責在執行完並經過全部NgModelController.$formatters方法後,呈現數據的方法。

  • 調用$setViewValue方法,不管任什麼時候候用戶與控件發生交互,model須要進行響應的更新。這一般在DOM事件監聽器裏實現。

  能夠查看$compileProvider.directivehttp://www.cnblogs.com/lcllao/archive/2012/09/09/2677190.html)獲取更多信息。

  下面的例子展現如何添加雙向數據綁定特性到能夠編輯的元素中。

<!DOCTYPE HTML>
<html 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>
    <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>
相關文章
相關標籤/搜索