0
0
Fork 0

Merge pull request '#7017 Show FormModel Validations' (!469) from 7017_formModel_validations into dev

Reviewed-on: verdnatura/salix-front#469
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
This commit is contained in:
Javier Segarra 2024-09-16 12:11:52 +00:00
commit af4756d810
4 changed files with 51 additions and 37 deletions

View File

@ -67,9 +67,13 @@ const mixinRules = [
requiredFieldRule, requiredFieldRule,
...($attrs.rules ?? []), ...($attrs.rules ?? []),
(val) => { (val) => {
const { min } = vnInputRef.value.$attrs; const { min, max } = vnInputRef.value.$attrs;
if (!min) return null; if (!min) return null;
if (min >= 0) if (Math.floor(val) < min) return t('inputMin', { value: min }); if (min >= 0) if (Math.floor(val) < min) return t('inputMin', { value: min });
if (!max) return null;
if (max > 0) {
if (Math.floor(val) > max) return t('inputMax', { value: max });
}
}, },
]; ];
</script> </script>
@ -116,8 +120,10 @@ const mixinRules = [
<i18n> <i18n>
en: en:
inputMin: Must be more than {value} inputMin: Must be more than {value}
inputMax: Must be less than {value}
es: es:
inputMin: Debe ser mayor a {value} inputMin: Debe ser mayor a {value}
inputMax: Debe ser menor a {value}
</i18n> </i18n>
<style lang="scss"> <style lang="scss">
.q-field__append { .q-field__append {

View File

@ -2,6 +2,7 @@
import { onMounted, watch, computed, ref } from 'vue'; import { onMounted, watch, computed, ref } from 'vue';
import { date } from 'quasar'; import { date } from 'quasar';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useAttrs } from 'vue';
const model = defineModel({ type: [String, Date] }); const model = defineModel({ type: [String, Date] });
const $props = defineProps({ const $props = defineProps({
@ -14,29 +15,19 @@ const $props = defineProps({
default: true, default: true,
}, },
}); });
import { useValidator } from 'src/composables/useValidator';
const { validations } = useValidator();
const { t } = useI18n(); const { t } = useI18n();
const requiredFieldRule = (val) => !!val || t('globals.fieldRequired'); const requiredFieldRule = (val) => validations().required($attrs.required, val);
const dateFormat = 'DD/MM/YYYY'; const dateFormat = 'DD/MM/YYYY';
const isPopupOpen = ref(); const isPopupOpen = ref();
const hover = ref(); const hover = ref();
const mask = ref(); const mask = ref();
const $attrs = useAttrs();
onMounted(() => { const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
// fix quasar bug
mask.value = '##/##/####';
});
const styleAttrs = computed(() => {
return $props.isOutlined
? {
dense: true,
outlined: true,
rounded: true,
}
: {};
});
const formattedDate = computed({ const formattedDate = computed({
get() { get() {
@ -48,16 +39,13 @@ const formattedDate = computed({
let newDate; let newDate;
if (value) { if (value) {
// parse input // parse input
if (value.includes('/')) { if (value.includes('/') && value.length >= 10) {
if (value.length == 6) value = value + new Date().getFullYear();
if (value.length >= 10) {
if (value.at(2) == '/') value = value.split('/').reverse().join('/'); if (value.at(2) == '/') value = value.split('/').reverse().join('/');
value = date.formatDate( value = date.formatDate(
new Date(value).toISOString(), new Date(value).toISOString(),
'YYYY-MM-DDTHH:mm:ss.SSSZ' 'YYYY-MM-DDTHH:mm:ss.SSSZ'
); );
} }
}
const [year, month, day] = value.split('-').map((e) => parseInt(e)); const [year, month, day] = value.split('-').map((e) => parseInt(e));
newDate = new Date(year, month - 1, day); newDate = new Date(year, month - 1, day);
if (model.value) { if (model.value) {
@ -79,12 +67,25 @@ const formattedDate = computed({
const popupDate = computed(() => const popupDate = computed(() =>
model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value model.value ? date.formatDate(new Date(model.value), 'YYYY/MM/DD') : model.value
); );
onMounted(() => {
// fix quasar bug
mask.value = '##/##/####';
});
watch( watch(
() => model.value, () => model.value,
(val) => (formattedDate.value = val), (val) => (formattedDate.value = val),
{ immediate: true } { immediate: true }
); );
const styleAttrs = computed(() => {
return $props.isOutlined
? {
dense: true,
outlined: true,
rounded: true,
}
: {};
});
</script> </script>
<template> <template>
@ -96,9 +97,10 @@ watch(
placeholder="dd/mm/aaaa" placeholder="dd/mm/aaaa"
v-bind="{ ...$attrs, ...styleAttrs }" v-bind="{ ...$attrs, ...styleAttrs }"
:class="{ required: $attrs.required }" :class="{ required: $attrs.required }"
:rules="$attrs.required ? [requiredFieldRule] : null" :rules="mixinRules"
:clearable="false" :clearable="false"
@click="isPopupOpen = true" @click="isPopupOpen = true"
hide-bottom-space
> >
<template #append> <template #append>
<QIcon <QIcon

View File

@ -1,8 +1,10 @@
<script setup> <script setup>
import { computed, ref } from 'vue'; import { computed, ref, useAttrs } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { date } from 'quasar'; import { date } from 'quasar';
import { useValidator } from 'src/composables/useValidator';
const { validations } = useValidator();
const $attrs = useAttrs();
const model = defineModel({ type: String }); const model = defineModel({ type: String });
const props = defineProps({ const props = defineProps({
timeOnly: { timeOnly: {
@ -16,8 +18,8 @@ const props = defineProps({
}); });
const initialDate = ref(model.value ?? Date.vnNew()); const initialDate = ref(model.value ?? Date.vnNew());
const { t } = useI18n(); const { t } = useI18n();
const requiredFieldRule = (val) => !!val || t('globals.fieldRequired'); const requiredFieldRule = (val) => validations().required($attrs.required, val);
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
const dateFormat = 'HH:mm'; const dateFormat = 'HH:mm';
const isPopupOpen = ref(); const isPopupOpen = ref();
const hover = ref(); const hover = ref();
@ -74,9 +76,10 @@ function dateToTime(newDate) {
v-bind="{ ...$attrs, ...styleAttrs }" v-bind="{ ...$attrs, ...styleAttrs }"
:class="{ required: $attrs.required }" :class="{ required: $attrs.required }"
style="min-width: 100px" style="min-width: 100px"
:rules="$attrs.required ? [requiredFieldRule] : null" :rules="mixinRules"
@click="isPopupOpen = false" @click="isPopupOpen = false"
type="time" type="time"
hide-bottom-space
> >
<template #append> <template #append>
<QIcon <QIcon

View File

@ -1,7 +1,8 @@
<script setup> <script setup>
import { ref, toRefs, computed, watch, onMounted } from 'vue'; import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import { useValidator } from 'src/composables/useValidator';
const emit = defineEmits(['update:modelValue', 'update:options', 'remove']); const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
const $props = defineProps({ const $props = defineProps({
@ -82,10 +83,11 @@ const $props = defineProps({
default: false, default: false,
}, },
}); });
const { validations } = useValidator();
const requiredFieldRule = (val) => validations().required($attrs.required, val);
const $attrs = useAttrs();
const { t } = useI18n(); const { t } = useI18n();
const requiredFieldRule = (val) => val ?? t('globals.fieldRequired'); const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } = const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } =
toRefs($props); toRefs($props);
const myOptions = ref([]); const myOptions = ref([]);
@ -248,8 +250,9 @@ const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
ref="vnSelectRef" ref="vnSelectRef"
lazy-rules lazy-rules
:class="{ required: $attrs.required }" :class="{ required: $attrs.required }"
:rules="$attrs.required ? [requiredFieldRule] : null" :rules="mixinRules"
virtual-scroll-slice-size="options.length" virtual-scroll-slice-size="options.length"
hide-bottom-space
> >
<template v-if="isClearable" #append> <template v-if="isClearable" #append>
<QIcon <QIcon