AngularJs進階-表單與驗證
本篇為【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、錄播視頻、細化知識點解析課堂等學習資源
週六上午開課,不佔用工作、學習時間
一餐飯的價格,汲取實戰角度的開發經驗
快來掃碼報名吧!
條件所限無法報名的同學,我們下週依然會將直播課的文字版更新在公眾號,歡迎前來討論學習~
推薦閱讀: