Есть форма с двумя полями. В компоненте
TheEducation.vue находится бизнес-логика и логика валидации полей, а в компоненте
BaseForm.vue происходит отрисовка полей и сохранение в локальное хранилище. Суть в том, что изначально шаблон работает с массивом
propList, который я передаю из
TheEducation в
BaseForm, и поля
"errorMessages":"error"
получают ошибки по необходимости. Всё работает. После перезагрузки страницы в компоненте
BaseForm отрабатывает уже ветка else:
if (!storedList) {
list.value = propList;
listType.value = 'propList: ' + JSON.stringify(list.value);
} else {
list.value = storedList;
listType.value = 'storedList: ' + JSON.stringify(list.value);
}
Соответственно, шаблон работает уже с данными из локального хранилища, и функция
getValidatePanels уже не присваивает массиву значение свойства errorMessages. В чем может быть проблема? Я полагаю, что возможно функция
getValidatePanels после перезагрузки страницы работает не с тем массивом. Во всяком случае, буду очень благодарен, если поможете разобраться. Это мой давний висяк, и я не могу решить его.
Песочницы:
https://replit.com/@teplandrey41/ValidationForm#sr...
https://codesandbox.io/p/sandbox/polished-morning-...
https://playcode.io/1843620
Код:
Родитель
<template>
<BaseForm
@blurEvent="handlePanelBlurEvent"
:personalDetailsPanelArr="personalDetailsPanelArr"
:educationPanelInputsArr="educationPanelInputsArr"/>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import BaseForm from './BaseForm.vue';
const educationPanelInputsArr = ref([
{ id: Math.floor(Math.random() * 100), name: 'InstituteName', errorMessages: '', validationData: 'EducationInstituteName', label: 'Name of educational institution', type: 'text', value: '', isEducationName: true },
{ id: Math.floor(Math.random() * 100), name: 'YearOfEntry', errorMessages: '', validationData: 'EducationYearOfEntry', label: 'Year of entry', type: 'number', value: ''}
]);
const personalDetailsPanelArr = ref([
{
id: Math.floor(Math.random() * 100),
type: 'Education',
title: 'Education',
isOpen: false,
inputs: educationPanelInputsArr.value,
}
]);
//"запрос на сервер" для получения валидации по полям
const getValidatePanels = () => {
let storedDataPanels = ref(JSON.parse(localStorage.getItem('personalDetailsEducationPanels')) || []);
//формирую объект с полями, value которых нужно будет провалидировать (отправить на сервер)
const newInitialPersonalDetailsListArray = storedDataPanels.value.map(item => {
const details = {};
item.inputs.forEach(input => {
details[input.validationData] = input.value;
});
return details;
});
//функция для присваивания возвращенных ошибок валидации с сервера
const extractDataFromPanels = (panel) => {
panel.forEach(inputField => {
const fieldName = inputField.validationData;
const foundInput = panel.find(input => input.validationData === fieldName);
if (foundInput.value.trim() === '') {
foundInput.errorMessages = 'error';
} else {
foundInput.errorMessages = '';
}
});
}
extractDataFromPanels(educationPanelInputsArr.value);
}
const handlePanelBlurEvent = () => {
getValidatePanels();
}
onMounted(() => {
getValidatePanels()
});
</script>
Потомок
<template>
<h1>{{ computedURLTitle }}</h1>
<div
v-for="(input, index) in allPanels" :key="index">
<hr>
<div
v-for="(inputField, inputIndex) in input.inputs"
:key="inputIndex">
<BaseInput
v-model="inputField.value"
:type="inputField.type"
:label="inputField.label"
@blur="$emit('blurEvent')"
/>
<div style="color: red;"> {{inputField.errorMessages}} </div>
</div>
</div>
<button @click="handleAddPanel">add</button>
<div style="color: blue;">{{ listType }}</div>
</template>
<script setup>
import { ref, defineProps, defineEmits, computed, watch } from 'vue';
import BaseInput from './BaseInput.vue';
import { useRouter } from 'vue-router';
const emits = defineEmits(['blurEvent']);
const router = useRouter();
const currentURL = ref(router.currentRoute.value.path);
const educationURL = '/education';
let listType = ref(null)
const props = defineProps({
personalDetailsPanelArr: {
type: Array,
},
educationPanelInputsArr: {
type: Array,
},
});
const pathTitles = {
'/education': 'Education',
};
const computedURLTitle = computed(() => {
const currentPath = currentURL.value;
return pathTitles[currentPath];
});
console.log('personalDetailsPanelArr: ', props.personalDetailsPanelArr)
let personalDetailsList = ref([]);
const storedPersonalDetailsList =
JSON.parse(localStorage.getItem('personalDetailsEducationPanels'));
if (storedPersonalDetailsList) {
personalDetailsList.value = storedPersonalDetailsList;
}
const updateLocalStorage = () => {
localStorage.setItem('personalDetailsEducationPanels', JSON.stringify(personalDetailsList.value));
}
const watchInput = (panel) => {
panel.inputs.forEach((input) => {
watch(input, (newValue) => {
if (newValue.isEducationName) {
panel.title = newValue.value || 'Education';
}
updateLocalStorage();
});
});
};
const panelLists = {
'/education': {
list: personalDetailsList,
storedList: storedPersonalDetailsList,
propList: props.personalDetailsPanelArr,
},
};
const allPanels = computed(() => {
const currentList = panelLists[currentURL.value];
if (currentList) {
const { list, storedList, propList } = currentList;
if (!storedList) {
list.value = propList;
listType.value = 'propList: ' + JSON.stringify(list.value);
} else {
list.value = storedList;
listType.value = 'storedList: ' + JSON.stringify(list.value);
}
list.value.forEach((panel) => {
watchInput(panel);
});
return list.value;
}
return [];
});
</script>