Salesforce LWC學習(十六) Validity 在form中的使用淺談
本篇參考:
https://developer.salesforce.com/docs/component-library/bundle/lightning-input/documentation
https://www.lightningdesignsystem.com/components/input/#Error
當我們在前端有表單操作或者有大量的輸入性條件作為搜尋條件情況下, 通常會有一些校驗,比如非空校驗,型別校驗等等。針對salesforce lwc也好或者是aura也好,通常有以下情況的前端校驗。
- badInput:用來判斷當前的輸入內容是否是一個合法的值;
- patternMismatch:用來判斷當前輸入內容是否符合指定模式;
- rangeOverflow:針對數字相關的型別判斷輸入內容是否值過大超過了預設的最大值;
- rangeUnderflow:針對數字相關的型別判斷輸入內容是否值過小小於預設的最小值;
- stepMismatch:針對數字相關的型別,我們在輸入框使用上或者下按鈕以後,可以根據step設定的值進行相關的輸入框內容的加或者減,當我們自己改的最終的值不符合step設定,會報錯stepMismatch;
- tooLong:指定value的長度是否超過當前設定的maxlength;
- tooShort:指定value的長度是否小於當前設定的minlength;
- typeMismatch:針對url或者email型別的變數,用來判斷當前輸入的value型別是否匹配;
- valueMissing:針對必填欄位沒有填值情況下會報錯這種型別錯誤。
當表單中校驗出現這種情況時,會展示相關的預設的錯誤提示資訊。
badInput
: Enter a valid value.patternMismatch
: Your entry does not match the allowed pattern.rangeOverflow
: The number is too high.rangeUnderflow
: The number is too low.stepMismatch
: Your entry isn't a valid increment.tooLong
tooShort
: Your entry is too short.typeMismatch
: You have entered an invalid format.valueMissing
: Complete this field.
下圖我們恐怕很熟悉了,經常看到類似當輸入框不滿足情況的預設的展示資訊。通過下圖可以更好的瞭解上面的一部分資訊。
上面截圖中的標紅的效果展示即為本篇講的validity,validity的使用可以使使用者在大量的入力操作部分不滿足情況下可以進行更好的定位,達到更好的使用者體驗。
標紅操作的css實現樣式可以檢視上方的參考連結。我們本篇考慮的更多是如何使用。
在form表單中的入力選擇的標籤大部分都內建了checkValidity / reportValidity / setCustomValidity或者類似函式。比如 input / combobox等等標籤。checkValidity用於驗證當前的表單的元素是否符合要求,reportValidity用於在checkValidity基礎上進行效果展示。如果當前元素符合要求,錯誤資訊清除並且return true;如果當前元素不符合要求,則展示錯誤資訊並且return false。
let allValid = [...this.template.querySelectorAll('lightning-input')] .reduce((validSoFar, inputFields) => { inputFields.reportValidity(); return validSoFar && inputFields.checkValidity(); }, true);
我們對上面的程式碼進行分析:
- 通過querySelectorAll獲取到當前元件中 lightning-input;
- 對每一個 lightning-input元素使用reportValidity方法進行校驗,如果當前元素符合要求,則返回true,如果不符合要求,返回false並且元素根據錯誤的型別展示錯誤的預設資訊;
- 通過checkValidity來確認當前元素是否符合,符合返回true,不符合返回false。
需要注意的是,當form表單提交的時候,如果頁面中有不符合的元素,並不會阻斷你的表單提交。所以我們在頁面提交以前如果看到了上面類似的提示不要掉以輕心,需要在save以前進行check,成功走save邏輯,不成功需要返回並且reportValidity()。
通過上面的demo中,我們可以看到使用querySelectorAll來遍歷所有lightning-input元素進行reportValidity和checkValidity,這種方式只能遍歷到當前component中的所有元素。如果元件包含了子元件,子元件中包含了 input等類似元素,並不能對子元件中的進行校驗。以一個demo進行試驗。
testSonInputComponent.html:僅用於展示一個輸入框
<template> <lightning-input label="test son" required></lightning-input> </template>
testParentInputComponent.html:引入testSonInputComponent並且在放一個input元件
<template> <lightning-layout multiple-rows="true"> <lightning-layout-item size="6"> <lightning-input label="test parent" type="text" required></lightning-input><br/> </lightning-layout-item> <lightning-layout-item size="6"> <c-test-son-input-component></c-test-son-input-component> </lightning-layout-item> <lightning-layout-item> <lightning-button label="validity" onclick={checkInputValidity}></lightning-button> </lightning-layout-item> </lightning-layout> </template>
testParentInputComponent.js:遍歷所有的input標籤,進行reportValidity操作。
import { LightningElement } from 'lwc'; export default class TestParentInputComponent extends LightningElement { checkInputValidity() { let allValid = [...this.template.querySelectorAll('lightning-input')] .reduce((validSoFar, inputFields) => { inputFields.reportValidity(); return validSoFar && inputFields.checkValidity(); }, true); console.log('result : ' + allValid); } }
效果展示:當標籤都沒有輸入情況下,只會校驗到當前元件中的標籤,子元件標籤不會被校驗到。
如果想要校驗到,目前想到的方法為父元件呼叫子元件的方法,可以將相關子元件的校驗功能彌補,但是無法將checkValidity的結果傳遞過來。如果想要檢視allValid,只能在父元件根據是否有值,然後手動設定allValid變數。程式碼簡單修改如下:
testInputSonComponent.js:對方法進行api標籤宣告,只有宣告以後父元件才可以呼叫。
import { LightningElement, api } from 'lwc'; export default class TestSonInputComponent extends LightningElement { @api checkInputValidity() { let allValid = [...this.template.querySelectorAll('lightning-input')] .reduce((validSoFar, inputFields) => { inputFields.reportValidity(); return validSoFar && inputFields.checkValidity(); }, true); } }
testInputParentComponent.js:通過querySelector獲取到子元件,然後呼叫子元件方法即可。
import { LightningElement } from 'lwc'; export default class TestParentInputComponent extends LightningElement { checkInputValidity() { let allValid = [...this.template.querySelectorAll('lightning-input')] .reduce((validSoFar, inputFields) => { inputFields.reportValidity(); return validSoFar && inputFields.checkValidity(); }, true); this.template.querySelector('c-test-son-input-component').checkInputValidity(); console.log('result : ' + allValid); } }
效果展示:
此種方式的一個最大的問題是子元件的validity的結果並無法傳遞給父元件。專案中是根據子元件的值是否為空在父元件中校驗然後設定allValid的值,除此以外沒有想到好的方法,熟悉的小夥伴可以給出更好的方案。
除了標準的提示資訊以外,lwc給我們提供了一個自定義error message的方法,即setCustomValidity。此方法在很多方法中均有類似的方法,用於當標準的提示資訊不滿足需求的時候或者自定義的一些校驗想要展示自定義的提示資訊情況下,使用的方案。當使用setCustomValidity,結合reportValidity即可展示自定義的error場景提示了。
對程式碼繼續改造。當輸入框內容不到2個字元進行自定義提示。
import { LightningElement } from 'lwc'; export default class TestParentInputComponent extends LightningElement { checkInputValidity() { let allValid = [...this.template.querySelectorAll('lightning-input')] .reduce((validSoFar, inputFields) => { if(inputFields.value.length < 2) { console.log('execute'); inputFields.setCustomValidity('輸入的長度應該超過2'); } inputFields.reportValidity(); return validSoFar && inputFields.checkValidity(); }, true); this.template.querySelector('c-test-son-input-component').checkInputValidity(); console.log('result : ' + allValid); } }
結果展示:
總結:篇中簡單的介紹了Validity的簡單實用,針對子元件如何更好的適應還沒有特別好的方案,有好想法的朋友留言。篇中有不懂的歡迎留言,有錯誤的歡迎指出。