本篇為【WEB零基礎全能課】JS篇第9節

歡迎到知乎專欄,獲取更多課程資料

修真院Web工程師零基礎全能課

本節課內容

AngularJs進階-表單與驗證

主講人介紹

沁修,葡萄藤技術總監

項目經驗豐富,擅長H5移動項目開發。

專註技術選型、底層開發、最佳代碼實踐規範總結與推廣。

直播錄屏版

文字解析版

大綱概述

簡單表單

增加css的表單

驗證

自定義驗證

在angularjs的開發中有一項必不可少的內容就是表單。

表單裏有大量控制項,如input,radio,select等,表單就是這些控制項的集合,可以將相關的控制項根據需要進行分組。

簡單表單

過去的表單開發中往往是這樣:

需要給每一個控制項添加一個id,然後找到id所在的DOM,對DOM綁定一些事件,來處理用戶的操作,以及及時給予反饋。

在angularjs中,我們有雙向數據綁定的ngModel

它提供了model和view之間的雙向數據綁定,大大的減輕了開發的工作量。

而且,ng中的form已經不是普通的form了,是一個被ng封裝過的指令:

可以完成普通form無法實現的功能,自帶強大的驗證功能。我們直接來段簡單表單的代碼:

<divng-controller="MyCtrl"class="ng-cloak">

<formnovalidate> <!— 會阻止默認的html5驗證,因為效果實在不是很好,我們希望自己來控制這一切。 —>

名字:<inputng-model="user.name"type="text"><br/>

Email:<inputng-model="user.email"type="email"><br/>

性別:<inputvalue="男"ng-model="user.gender"type="radio">男

<inputvalue="女"ng-model="user.gender"type="radio">女

<br/>

<buttonng-click="reset()">還原上次保存</button>

<buttonng-click="update(user)">保存</button>

<buttonng-click="clean()">清空</button>

</form>

<pre>form = {{user | json}}</pre>

<pre>data = {{data | json}}</pre>

</div>

<scripttype="text/javascript">

varapp=angular.module("SimpleForm", []);

app.controller("MyCtrl",function($scope,$window) {

$scope.data={};

$scope.update=function(user) {

$scope.data=angular.copy(user);

};

$scope.reset=function() {

$scope.user=angular.copy($scope.data);

};

$scope.clean=function() {

$scope.user={};

}

});

</script>

// 不合法的值是不會進入user的

ngModel是表單中的核心指令,同時也是一個使用頻率非常非常高的指令:

它不止提供了數據綁定,還有驗證,樣式更新,數據格式化,編譯功能。

如果不設置ngModel,那麼angluar就無法知道form.$valid的值是否為真。

的input控制項自帶一些驗證選項

<input

ng-model=""

[name=""]

[required=""]

[ng-required=""]

[ng-minlength=""]

[ng-maxlength=""]

[ng-pattern=""]

[ng-change=""]>

...

</input>

加上樣式的表單

ng在驗證輸入或表單的有效性的時候已經提供了一些默認類。

因此可以編輯自己喜歡的的css,私有化的定製這些類來實現特定的場景應用

.ng-valid { }

.ng-invalid { }

.ng-pristine { }

.ng-dirty { }

/* really specific css rules applied by angular */

.ng-invalid-required { }

.ng-invalid-minlength { }

.ng-valid-max-length { }

那麼改造一下剛剛那個表單,讓它交互性更強:

<styletype="text/css">

input.ng-invalid.ng-dirty {

background-color:#fa787e;

}

input.ng-valid.ng-dirty {

background-color:#78fa89;

}

</style>

<divng-controller="MyCtrl"class="ng-cloak">

<formnovalidate>

名字:<inputng-model="user.name"type="text"required><br/>

Email:<inputng-model="user.email"type="email"required><br/>

性別:<inputvalue="男"ng-model="user.gender"type="radio">男

<inputvalue="女"ng-model="user.gender"type="radio">女

<br/>

<buttonng-click="reset()">還原上次保存</button>

<buttonng-click="update(user)">保存</button>

<buttonng-click="clean()">清空</button>

</form>

<pre>form = {{user | json}}</pre>

<pre>data = {{data | json}}</pre>

</div>

<scripttype="text/javascript">

varapp=angular.module("SimpleForm", []);

app.controller("MyCtrl",function($scope,$window) {

$scope.data={};

$scope.update=function(user) {

$scope.data=angular.copy(user);

};

$scope.reset=function() {

$scope.user=angular.copy($scope.data);

};

$scope.clean=function() {

$scope.user={};

}

});

</script>

表單與控制器

在angualrjs中,ng-controller作用域當中的form表單,可以使用name屬性將它暴露到scope中。

我們再次來改造一下這個表單,給它加上一些簡單的驗證,要求是:

name必填

email必填

表單保存過就不能再保存

表單和保存的內容一致就無法再保存

<divng-controller="MyCtrl"class="ng-cloak">

<formnovalidatename="formName">

名字:<inputng-model=「user.name」 name=「userName" type="text"required><br/>

<divng-show="formName.userName.$dirty&&formName.userName.$invalid">

<span>請填寫名字</span>

</div>

Email:<inputng-model=「user.email」 name=「emailName"type="email"required><br/>

<divng-show="formName.userEmail.$dirty && formName.userEmail.$invalid">提示:

<spanng-show="formName.userEmail.$error.required">請填寫Email</span>

<spanng-show="formName.userEmail.$error.email">這不是一個有效的Email</span>

</div>

性別:<inputvalue="男"ng-model="user.gender"type="radio">男

<inputvalue="女"ng-model="user.gender"type="radio">女

<br/>

<buttonng-click="reset()"ng-disabled="isUnchanged(user)">還原上次</button>

<buttonng-click="update(user)"ng-disabled="formName.$invalid || isUnchanged(user)">保存</button>

<buttonng-click="clean()">清空</button>

</form>

<pre>form = {{user | json}}</pre>

<pre>data = {{data | json}}</pre>

</div>

<scripttype="text/javascript">

varapp=angular.module("SimpleForm", []);

app.controller("MyCtrl",function($scope,$window) {

$scope.data={};

$scope.update=function(user) {

$scope.data=angular.copy(user);

};

$scope.reset=function() {

$scope.user=angular.copy($scope.data);

};

$scope.clean=function() {

$scope.user={};

}

$scope.isUnchanged=function(user) {

returnangular.equals(user,$scope.data);

};

});

事實上是這樣的,ng的表單提供了很多屬性來幫助我們驗證它

屬性class說明$validng-valid驗證是否通過$invalidng-invalid驗證是否未通過$pristineng-pristine表單和控制項是否沒使用過$dirtyng-dirty表單和控制項是否使用過

如果我們要訪問表單屬性就可以:

form-name.angular-property

如果是訪問輸入框屬性則可以:

form-name.input-name.angular-property

如果想禁用表單按鈕,非常簡單,如果整個表單沒通過驗證,就會禁用,那就只需要加上這樣的代碼

ng-disabled="formName.$invalid」

這也說明,我們input和form的name欄位是必須加的,需要通過這樣的鏈式調用法訪問到屬性。

更漂亮的驗證

如果我們給我們的網站加上bootstrap,就可以使用它提供的類,來圍繞我們的表單做更好看的信息和顏色了。

這個時候我們會用到ng-class,它允許我們基於一個表達式來添加類。

比如如果輸入框的狀態是$invalid或者不是$pristine的話,我們想要添加一個has-error類,就可以這樣:

ng-class=「{<class>: <express>}"

<!-- USERNAME -->

<divclass="form-group"ng-class="{ has-error : userForm.username.$invalid && !userForm.username.$pristine }">

<label>Username</label>

<inputtype="text"name="username"class="form-control"ng-model="user.username"ng-minlength="3"ng-maxlength="8">

<png-show="userForm.username.$error.minlength"class="help-block">Username is too short.</p>

<png-show="userForm.username.$error.maxlength"class="help-block">Username is too long.</p>

</div>

<!-- EMAIL -->

<divclass="form-group"ng-class="{ has-error : userForm.email.$invalid && !userForm.email.$pristine }">

<label>Email</label>

<inputtype="email"name="email"class="form-control"ng-model="user.email">

<png-show="userForm.email.$invalid && !userForm.email.$pristine"class="help-block">Enter a valid email.</p>

</div>

自定義的驗證

ng為表單驗證默認提供了一些directive,比如:

required,pattern,minlenth,maxlength,min,max。

但我們可以通過定義這些指令增加驗證規則。這些指令寫起來很好玩,同時它們也有一些規則需要掌握:

1.model更新到view的時候。

model發生的改變,都在ngModelController.$formatters數組中排隊執行,然後通過$setValidity去修改控制項的驗證狀態

2.view更新到model的時候。

是這樣的,當用戶和控制項發生交互,會觸發$setViewValue。

然後就需要執行$parsers數組中的方法,去從控制項中得到值,然後進行過濾或轉換或驗證。

<divclass="ng-cloak">

<formnovalidateclass="css-form"name="formName">

<div>

大小(整數 0 - 10):<inputintegertype="number"ng-model="size"name="size"min="0"max="10"/>{{size}}<br/>

<spanng-show="formName.size.$error.integer">這不是一個有效的整數</span>

<spanng-show="formName.size.$error.min || formName.size.$error.max">

數值必須在0到10之間

</span>

</div>

<div>

長度(浮點數):

<inputtype="text"ng-model="length"name="length"smart-float/>

{{length}}<br/>

<spanng-show="formName.length.$error.float">這不是一個有效的浮點數</span>

</div>

</form>

<pre>form = {{user | json}}</pre>

<pre>data = {{data | json}}</pre>

</div>

<scripttype="text/javascript">

varapp=angular.module("SimpleForm", []);

varINTEGER_REGEXP=/^-?d*$/;

app.directive("integer",function() {

return{

require:"ngModel",

link:function(scope,ele,attrs,ctrl) {

ctrl.$parsers.unshift(function(viewValue) {

if(INTEGER_REGEXP.test(viewValue)) {

ctrl.$setValidity("integer",true);

returnviewValue;

}else{

ctrl.$setValidity("integer",false);

returnundefined;

}

});

}

};

});

varFLOAT_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);

returnparseFloat(viewValue.replace(",","."));

}else{

ctrl.$setValidity("float",false);

returnundefined;

}

});

}

}

});

</script>

以上就是上節課的內容解析啦

想進一步深入的同學歡迎加入我們的IT交流羣828691304共同交流學習!

下節預告

AngularJs伺服器通信

報名聽課的同學們將獲得:

1、與技術總監級別的一線開發人員接觸、提問機會

2、來自真實項目的應用開發技巧、代碼規範

3、與直播課程配套的任務體系、日報體系

4、分配一對一的專屬師兄,進行技術輔導

5、課程PPT、錄播視頻、細化知識點解析課堂等學習資源

週六上午開課,不佔用工作、學習時間

一餐飯的價格,汲取實戰角度的開發經驗

快來掃碼報名吧!

條件所限無法報名的同學,我們下週依然會將直播課的文字版更新在公眾號,歡迎前來討論學習~


推薦閱讀:
相關文章