123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- // Composables
- import { makeFocusProps } from "./focus.mjs";
- import { useForm } from "./form.mjs";
- import { useProxiedModel } from "./proxiedModel.mjs";
- import { useToggleScope } from "./toggleScope.mjs"; // Utilities
- import { computed, nextTick, onBeforeMount, onBeforeUnmount, onMounted, ref, shallowRef, unref, watch } from 'vue';
- import { getCurrentInstanceName, getUid, propsFactory, wrapInArray } from "../util/index.mjs"; // Types
- export const makeValidationProps = propsFactory({
- disabled: {
- type: Boolean,
- default: null
- },
- error: Boolean,
- errorMessages: {
- type: [Array, String],
- default: () => []
- },
- maxErrors: {
- type: [Number, String],
- default: 1
- },
- name: String,
- label: String,
- readonly: {
- type: Boolean,
- default: null
- },
- rules: {
- type: Array,
- default: () => []
- },
- modelValue: null,
- validateOn: String,
- validationValue: null,
- ...makeFocusProps()
- }, 'validation');
- export function useValidation(props) {
- let name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstanceName();
- let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getUid();
- const model = useProxiedModel(props, 'modelValue');
- const validationModel = computed(() => props.validationValue === undefined ? model.value : props.validationValue);
- const form = useForm();
- const internalErrorMessages = ref([]);
- const isPristine = shallowRef(true);
- const isDirty = computed(() => !!(wrapInArray(model.value === '' ? null : model.value).length || wrapInArray(validationModel.value === '' ? null : validationModel.value).length));
- const isDisabled = computed(() => !!(props.disabled ?? form?.isDisabled.value));
- const isReadonly = computed(() => !!(props.readonly ?? form?.isReadonly.value));
- const errorMessages = computed(() => {
- return props.errorMessages.length ? wrapInArray(props.errorMessages).slice(0, Math.max(0, +props.maxErrors)) : internalErrorMessages.value;
- });
- const validateOn = computed(() => {
- let value = (props.validateOn ?? form?.validateOn.value) || 'input';
- if (value === 'lazy') value = 'input lazy';
- const set = new Set(value?.split(' ') ?? []);
- return {
- blur: set.has('blur') || set.has('input'),
- input: set.has('input'),
- submit: set.has('submit'),
- lazy: set.has('lazy')
- };
- });
- const isValid = computed(() => {
- if (props.error || props.errorMessages.length) return false;
- if (!props.rules.length) return true;
- if (isPristine.value) {
- return internalErrorMessages.value.length || validateOn.value.lazy ? null : true;
- } else {
- return !internalErrorMessages.value.length;
- }
- });
- const isValidating = shallowRef(false);
- const validationClasses = computed(() => {
- return {
- [`${name}--error`]: isValid.value === false,
- [`${name}--dirty`]: isDirty.value,
- [`${name}--disabled`]: isDisabled.value,
- [`${name}--readonly`]: isReadonly.value
- };
- });
- const uid = computed(() => props.name ?? unref(id));
- onBeforeMount(() => {
- form?.register({
- id: uid.value,
- validate,
- reset,
- resetValidation
- });
- });
- onBeforeUnmount(() => {
- form?.unregister(uid.value);
- });
- onMounted(async () => {
- if (!validateOn.value.lazy) {
- await validate(true);
- }
- form?.update(uid.value, isValid.value, errorMessages.value);
- });
- useToggleScope(() => validateOn.value.input, () => {
- watch(validationModel, () => {
- if (validationModel.value != null) {
- validate();
- } else if (props.focused) {
- const unwatch = watch(() => props.focused, val => {
- if (!val) validate();
- unwatch();
- });
- }
- });
- });
- useToggleScope(() => validateOn.value.blur, () => {
- watch(() => props.focused, val => {
- if (!val) validate();
- });
- });
- watch(isValid, () => {
- form?.update(uid.value, isValid.value, errorMessages.value);
- });
- function reset() {
- model.value = null;
- nextTick(resetValidation);
- }
- function resetValidation() {
- isPristine.value = true;
- if (!validateOn.value.lazy) {
- validate(true);
- } else {
- internalErrorMessages.value = [];
- }
- }
- async function validate() {
- let silent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- const results = [];
- isValidating.value = true;
- for (const rule of props.rules) {
- if (results.length >= +(props.maxErrors ?? 1)) {
- break;
- }
- const handler = typeof rule === 'function' ? rule : () => rule;
- const result = await handler(validationModel.value);
- if (result === true) continue;
- if (result !== false && typeof result !== 'string') {
- // eslint-disable-next-line no-console
- console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`);
- continue;
- }
- results.push(result || '');
- }
- internalErrorMessages.value = results;
- isValidating.value = false;
- isPristine.value = silent;
- return internalErrorMessages.value;
- }
- return {
- errorMessages,
- isDirty,
- isDisabled,
- isReadonly,
- isPristine,
- isValid,
- isValidating,
- reset,
- resetValidation,
- validate,
- validationClasses
- };
- }
- //# sourceMappingURL=validation.mjs.map
|