11<script setup lang="ts">
2- import { toRefs , useTemplateRef } from ' vue'
2+ import { useTemplateRef } from ' vue'
33import { useI18n } from ' vue-i18n'
44
55import { useComponentUniqueId } from ' @/utils/composables/useComponentUniqueId'
6- import { useFieldValidation } from ' @/utils/composables/useFieldValidation'
6+ import {
7+ useFieldValidation ,
8+ type ValidateFunction ,
9+ type ValidationResult ,
10+ } from ' @/utils/composables/useFieldValidation'
711import { isValidEmail } from ' @/utils/utils'
812
9- const props = withDefaults (
10- defineProps <{
11- /** Label to add above the field */
12- label? : string
13- /** Description to add below the input */
14- description? : string
15- /** Mark the field as disable */
16- disabled? : boolean
17- /**
18- * Placeholder text
19- *
20- * NOTE: this should be a translation key
21- */
22- placeholder? : string
23- /** Field is required and will be marked as invalid if empty */
24- required? : boolean
25- /**
26- * Mark the field as valid
27- *
28- * This can be used if the field requires some external validation. When not set or set to
29- * undefined this props is ignored.
30- *
31- * NOTE: this props is ignored when activate-validation is false
32- */
33- validMarker? : boolean | undefined
34- /**
35- * Valid message Message that will be added in green below the field once the validation has
36- * been done and the field is valid.
37- */
38- validMessage? : string
39- /**
40- * Mark the field as invalid
41- *
42- * This can be used if the field requires some external validation. When not set or set to
43- * undefined this props is ignored.
44- *
45- * NOTE: this props is ignored when activate-validation is false
46- */
47- invalidMarker? : boolean | undefined
48- /**
49- * Invalid message Message that will be added in red below the field once the validation has
50- * been done and the field is invalid.
51- *
52- * NOTE: this message is overwritten if the internal validation failed (not allow file type
53- * or file too big or required empty file)
54- */
55- invalidMessage? : string
56- /**
57- * Mark the field has validated.
58- *
59- * As long as the flag is false, no validation is run and no validation marks are set. Also
60- * the props is-invalid and is-valid are ignored.
61- */
62- activateValidation? : boolean
63- /**
64- * Validate function to run when the input changes The function should return an object of
65- * type `{valid: Boolean, invalidMessage: String}`. The `invalidMessage` string should be a
66- * translation key.
67- *
68- * NOTE: this function is called each time the field is modified
69- */
70- validate? : ((_value ? : string ) => { valid: boolean ; invalidMessage: string }) | undefined
71- dataCy? : string
72- }>(),
73- {
74- validMarker: undefined ,
75- invalidMarker: undefined ,
76- }
77- )
78-
79- const { label, description, disabled, placeholder, dataCy } = toRefs (props )
13+ const {
14+ label = ' ' ,
15+ description = ' ' ,
16+ disabled = false ,
17+ placeholder = ' ' ,
18+ required = undefined ,
19+ forceValid = undefined ,
20+ validMessage,
21+ forceInvalid = undefined ,
22+ invalidMessage,
23+ activateValidation = undefined ,
24+ validate,
25+ dataCy = ' ' ,
26+ } = defineProps <{
27+ /** Label to add above the field */
28+ label? : string
29+ /** Description to add below the input */
30+ description? : string
31+ /** Mark the field as disable */
32+ disabled? : boolean
33+ /**
34+ * Placeholder text
35+ *
36+ * NOTE: this should be a translation key
37+ */
38+ placeholder? : string
39+ /** Field is required and will be marked as invalid if empty */
40+ required? : boolean
41+ /**
42+ * Mark the field as valid
43+ *
44+ * This can be used if the field requires some external validation. When not set or set to
45+ * undefined this props is ignored.
46+ *
47+ * NOTE: this props is ignored when activate-validation is false
48+ */
49+ forceValid? : boolean
50+ /**
51+ * Valid message Message that will be added in green below the field once the validation has
52+ * been done and the field is valid.
53+ */
54+ validMessage? : string
55+ /**
56+ * Mark the field as invalid
57+ *
58+ * This can be used if the field requires some external validation. When not set or set to
59+ * undefined this props is ignored.
60+ *
61+ * NOTE: this props is ignored when activate-validation is false
62+ */
63+ forceInvalid? : boolean
64+ /**
65+ * Invalid message Message that will be added in red below the field once the validation has
66+ * been done and the field is invalid.
67+ *
68+ * NOTE: this message is overwritten if the internal validation failed (not allow file type or
69+ * file too big or required empty file)
70+ */
71+ invalidMessage? : string
72+ /**
73+ * Mark the field has validated.
74+ *
75+ * As long as the flag is false, no validation is run and no validation marks are set. Also the
76+ * props is-invalid and is-valid are ignored.
77+ */
78+ activateValidation? : boolean
79+ /**
80+ * Validate function to run when the input changes The function should return an object of type
81+ * `{valid: Boolean, invalidMessage: String}`. The `invalidMessage` string should be a
82+ * translation key.
83+ *
84+ * NOTE: this function is called each time the field is modified
85+ */
86+ validate? : ValidateFunction <string >
87+ dataCy? : string
88+ }>()
8089
8190const inputEmailId = useComponentUniqueId (' email-input' )
82-
8391const model = defineModel <string >({ default: ' ' })
92+
8493const emits = defineEmits <{
8594 change: [void ]
86- validate: [isValid : boolean ]
95+ validate: [validation : ValidationResult ]
8796 focusin: [void ]
8897 focusout: [void ]
8998 ' keydown.enter' : [void ]
9099}>()
91100const { t } = useI18n ()
92101
93- const {
94- value,
95- validMarker : computedValidMarker,
96- invalidMarker : computedInvalidMarker,
97- invalidMessage : computedInvalidMessage,
98- onFocus,
99- } = useFieldValidation (props , model , emits , {
100- customValidate: validateEmail ,
102+ const { validation, onFocus } = useFieldValidation <string >({
103+ model ,
104+
105+ required ,
101106 requiredInvalidMessage: ' no_email' ,
107+
108+ activateValidation ,
109+
110+ forceValid ,
111+ validFieldMessage: validMessage ,
112+
113+ forceInvalid ,
114+ invalidFieldMessage: invalidMessage ?? ' invalid_email' ,
115+
116+ emits ,
117+ validate: validateEmail ,
102118})
103119
104120const emailInputElement = useTemplateRef <HTMLInputElement >(' emailInputElement' )
105121
106- function validateEmail() {
107- if (value .value && ! isValidEmail (value .value )) {
108- return { valid: false , invalidMessage: ' invalid_email' }
122+ function validateEmail(email ? : string ): ValidationResult {
123+ if (email && ! isValidEmail (email )) {
124+ return { valid: false , invalidMessage: invalidMessage ?? ' invalid_email' }
125+ }
126+ if (validate ) {
127+ return validate (email )
109128 }
110129 return { valid: true , invalidMessage: ' ' }
111130}
@@ -134,11 +153,11 @@ defineExpose({ focus })
134153 <input
135154 :id =" inputEmailId"
136155 ref =" emailInputElement"
137- v-model =" value "
156+ v-model =" model "
138157 :disabled =" disabled"
139158 :class =" {
140- 'is-invalid': computedInvalidMarker ,
141- 'is-valid': computedValidMarker ,
159+ 'is-invalid': validation && !validation.valid ,
160+ 'is-valid': validation && validation.valid ,
142161 }"
143162 type =" email"
144163 class =" form-control"
@@ -150,11 +169,11 @@ defineExpose({ focus })
150169 @keydown.enter =" emits('keydown.enter')"
151170 />
152171 <div
153- v-if =" computedInvalidMessage "
172+ v-if =" validation?.invalidMessage "
154173 class =" invalid-feedback"
155174 data-cy =" email-input-invalid-feedback"
156175 >
157- {{ t(computedInvalidMessage ) }}
176+ {{ t(validation.invalidMessage ) }}
158177 </div >
159178 <div
160179 v-if =" validMessage"
0 commit comments