如何優雅的使用 Angular 表單驗證

隨便說說,這一節能夠跳過

去年參加 ngChine 2018 杭州開發者大會的時候記得有人問我: Worktile 是何時開始使用 Angular 的,我說是今年(2018年) 3 月份開始在新模塊中使用最新的 Angular 6,他說是否是有點晚了,我當時愣了一下。 其實仔細回想了一下, Angular 2.0 正式發佈也就在 2016-09-14 號,因此也就晚了 1 年多一點點纔開始使用而已嘛,再加上 2.0 到 4.0 的過渡或多或少仍是有一點點坑的,不是很穩定,此時投入不是特別合適,雖然升級簡單,可是仍是有不少概念和API須要從新學習,好比 HttpClient,路由等等(在 2.0 的時候咱們是有嘗試在邊緣的一個 Open API Doc 文檔站點使用過的,咱們一直在關注着最新的 Angular)html

因此我以爲 4.0 (也就是 2017-03)以後的 Angular 才真真正正的開始趨於穩定,能夠開始嘗試學習和使用,再加上通過了 1 年多的社區實踐,踩坑,基礎生態建設,我以爲今年(2018年)纔是企業大規模嘗試使用 Angular 最佳時間點,再加上 Angular CLI 以及 @angular/cdk的逐漸強大, 我想說這是一個最好的時代。前端

另外還有一個緣由是 2016 - 2017 年屬於我司最艱難的困難時期,壓根沒有心思考慮切換最新技術棧,因此那 2 年基本上屬於埋頭作業務。react

如今回過頭來看 Angular ,在前端框架高速發展的那幾年,由於正式版發佈遲遲延期,致使市場被後起之秀 React, Vue 等優秀框架佔有,好在新的 Angular 足夠優秀,足夠前瞻,值得花更多的時間投入學習和使用,如今還不算晚。因此慢有必定道理的,由於須要精雕玉琢,衡量將來的趨勢等等,可是從完美支持 TypeScript,RxJS 這 2 點來講,Angular 的確走在了前面。git

迴歸正題,說到表單,我認爲一個強大表單應該包含下面3部分功能

1.收集用戶的輸入的表單數據,在 Angular 中經過 ngModel 實現雙向綁定很是方便;程序員

2.經過各類驗證器驗證表單元素輸入的數據是否合法,Angular 內置了經常使用的驗證器(required、pattern、email,min,max,minLength,maxLength);github

3.驗證後給予用戶反饋,好比驗證不經過給予錯誤的提示信息。前端框架

我以爲 Angular 的表單無疑是三大框架中最強大的,沒有之一,並且是官方原生提供支持和維護,提到 Angular 的表單確定要說下 Angular.js 的表單,其實 Angular 的表單基本上繼承了 Angular.js 表單的全部功能,同時比 Angular.js 更強大,API 更友好。antd

另外說下本文不是普及 Angular Form 表單的基本知識的,若是有不瞭解的能夠看 angular forms guide ,由於官方文檔已經寫的特別好了。框架

那麼 Angular 的表單和 Angular.js 相比到底有哪些改進呢?

自定義 ngModel

在 Angular.js 中 ng-model 只能用於 input,select 等內置的 HTML 表單元素,若是是一個自定義的 select 框(div),可能就沒法使用自帶的 required 等驗證器了異步

可是能夠經過猥瑣的方式處理,好比加一個隱藏的原生 HTML 表單元素,這個元素上綁定的 ng-model 和自定義的 select 框的 model 是同樣的,而後經過這個隱藏元素是否驗證經過去控制自定義 Select 的驗證樣式

那麼在 Angular 中能夠很方便讓任何自定義的組件使用 ngModel 和 內置的驗證器,只要你的自定義組件實現 ControlValueAccessor 接口,同時在組件的 providers 中加上 NGVALUEACCESSOR 的 provider 便可,具體如何實現一個自定義的支持 ngModel 組件自行搜索下,官方文檔好像沒有找到相關介紹, 附一個 stackoverflow question

結構型指令內部的表單元素自動識別

在 Angular.js 中若是有 ng-if 之類的動態指令,內部的表單元素不會自動追加到 Form 上,必須經過擴展一個自定義指令 dynamicFormControl 去手動追加到 ngForm 上,可是在 Angular 中不須要用戶本身去處理,只要元素被渲染,會自動附加到 ngForm Controls 中。

響應式表單

Angular 中除了模板驅動表單外,還新增了響應式表單,讓用戶多了一份選擇,在某些複雜的場景下,響應式表單會更有優點。

動態表單支持更好

在 Angular 中不論是模板驅動表單仍是響應式表單,對於動態建立表單的支持都很好,能夠輕鬆的經過 [attr.name]="formName"[name]="formName" 實現動態表單元素的建立。若是有複雜的驗證器,那麼使用 響應式表單 會更好。

模板驅動表單驗證器支持屬性綁定,動態控制是否須要驗證

若是一個表單元素(好比說用戶名)是否爲必填不是肯定的,而是動態設置的, 在 Angular 中能夠經過屬性綁定 [required]="isRequired" 很是方便的控制,我看了下 Angular.js 的源碼如今也是支持的,不知道是我之前沒有發現呢仍是以後的版本加上的功能。

支持異步驗證器

若是要驗證用戶名輸入是否已經存在,就須要請求 API 遠程驗證,那麼這個驗證就是一個異步,若是驗證不支持就會致使驗證結果沒有返回的時候就直接提交表單了。若是支持異步會更加的完善。

經過上述的幾點來看, Angular 表單基本已經完美了,可是

咱們還須要讓驗證錯誤提示更加簡單

回頭再看下開頭的介紹的表單應該包含下面3部分功能:

1. 收集用戶的輸入的表單數據; 這個基本上 ngModel 雙向綁定的語法糖已經簡化的不能再簡化了,固然使用響應式表單連 ngModel 也能夠不寫;

2. 內置的驗證器知足大部分場景,可是仍是會有不少經常使用的驗證器官方沒有提供,好比 重複驗證,遠程惟一性驗證等等,@Nightapes/ngx-validators@gangachris/ng-validators 這2個第三方庫擴展了不少,即便不知足本身擴展也很簡單;

3. 驗證後給予用戶反饋,驗證不經過給予錯誤的提示信息。對於這個錯誤提示信息,每一個產品每一個用戶都會有不同的需求,Angular 把能夠作到的都作到了,都自動追加了 ng-invalidng-validng-touched 等 class,還有就是哪些元素哪一個驗證器驗證失敗均可以從 ngModel 和 ngForm 方便的獲取到,錯誤提示只能交給用戶本身去處理。

對於驗證錯誤提示,手動寫錯誤提示的模版會很囉嗦,寫模版自己也沒什麼,怕就怕哪天設計師改需求了,原有的提示方式換了一個新的方式,那整個系統都須要挨個替換,有追求的程序員最怕的就是作重複沒有含量的工做,並且有時候還沒法經過批量替換完成,因此在使用 Angular.js 1.x 的時候我就封裝了一個表單驗證庫 angular-w5c-validator,剛開始發佈的時候功能比較簡單,後來有人提各類 Issue,逐漸改善,我以爲這個驗證庫對於不少人來講仍是有幫助的,至少我以爲是更優雅的處理了各類錯誤提示,star 很少,可是證實了這個封裝仍是有必定價值的。

那麼咱們即便如今升級到了 Angular ,也面臨着錯誤提示如何處理的問題,固然也有些類庫處理了相關問題,可是好像都沒有找到特別好用的。

1.ngx-errors 仍是手寫模版,只是簡化了寫法。

2.ng-zorro-antd 組件庫關於表單組件對錯誤驗證提示也作了不少工做,可是仍是須要手寫模版配置。

既然沒有相關的類庫符合咱們的需求,那麼顯然就須要本身造輪子,因此咱們去年在升級 Angular 時就按照咱們的方式在組件庫的 Form 表單模塊加上了和 Angular.js angular-w5c-validator 相似的 API,得益於 Angular 框架的優秀,造起輪子特別簡單。

內部的組件庫暫時還沒法開源出去讓更多人使用,可是的可是

ngx-validator 已經能夠開始使用了

因此這周我單獨抽離了表單驗證功能爲一個獨立的組件 ngx-validator , 若是你也再爲表單驗證錯誤提示苦惱,也在尋找一種更優雅的錯誤處理方式,但願個人這個庫能夠幫助到你或者給你一個啓發。

ngx-validator Demo 示例,點擊直接查看演示

ngx-validator.gif

最後的最後感謝你耐心閱讀到此,這篇博客已經計劃了 3 個多月了,由於工做繁忙一直沒有時間,這週末下了一個狠心,必須完成!已經被兒子打擾屢次,還有就是 ngx-validator 目前基本的功能已經完成,後期還有不少加強的驗證器,測試須要補充,還不是特別完善,歡迎你們提寶貴意見。

 

本文做者:徐海峯

文章來源:Worktile技術博客

歡迎訪問交流更多關於技術及協做的問題。

文章轉載請註明出處。

相關文章
相關標籤/搜索