Обработка события OnChange с помощью функции handleChangeEvent
Сейчас, если мы введем что-то в поля ввода, ничего не произойдет. Это потому, что в нашем файле InputConfiguration.js
все свойства value
установлены на пустые строки для всех входов (кроме datePicker, он принимает функцию moment()
, которая всегда применяет текущую дату). Более важно то, что мы никогда не изменяем свойство value
внутри объекта конфигурации, то есть пустые поля ввода.
Мы собираемся исправить это и добавить проверку, реализовав функцию handleChangeEvent
.
Давайте изменим файл CreateOwner.js
, добавив функцию handleChangeEvent
под обработчиком жизненного цикла componentWillMount
:
handleChangeEvent = (event, id) => {
const updatedOwnerForm = { ...this.state.ownerForm };
updatedOwnerForm[id] = formUtilityActions.executeValidationAndReturnFormElement(event, updatedOwnerForm, id);
const counter = formUtilityActions.countInvalidElements(updatedOwnerForm);
this.setState({ ownerForm: updatedOwnerForm, isFormValid: counter === 0 })
}
Эта функция принимает два параметра. Параметр event
, который содержит значение из наших полей ввода (не только значение, но это важно для нас), и параметр id
, которому мы собираемся передать один из ключей объекта конфигурации (имя, адрес или дату рождения).
Мы глубоко клонируем ownerForm
из состояния, а затем обновляем конфигурацию текущего измененного входа, вызывая функцию executeValidationAndReturnFormElement
. После проверки мы подсчитываем, сколько полей недействительно, и если таковые имеются, наша полная форма будет отмечена как недействительная. Наконец, мы собираемся обновить состояние.
Создание дополнительных функций для проверки формы React
У нас есть функции executeValidationAndReturnFormElement и countInvalidElements, но они еще не созданы.
Итак, давайте создадим их.
Давайте изменим файл FormUtility.js
:
export const executeValidationAndReturnFormElement = (event, updatedOwnerForm, id) => {
let formElement = { ...updatedOwnerForm[id] };
formElement.value = id === 'dateOfBirth' ? event : event.target.value;
formElement.touched = true;
const validationResponse = checkValidity(formElement.value, formElement.validation);
formElement.valid = validationResponse.isValid;
formElement.errorMessage = validationResponse.errorMessage;
return formElement;
}
Во-первых, мы клонируем точный formElement
, который пользователь в настоящее время изменяет. Затем заполните значение formElement
с помощью тернарного оператора (если пользователь изменяет ввод dateOfBirth
, то значением является event
. Но для любого другого поля ввода event
является объектом, имеющим свойство target
, которое содержит свойство value
). Кроме того, мы собираемся установить для нашего элемента управления значение касания, а затем отправить значение и правила проверки в процесс проверки. После завершения процесса мы сохраняем эти результаты. Наконец, мы возвращаем formElement
со всеми изменениями.
Реализация функции CheckValidity
Итак, давайте реализуем функцию checkValidity
непосредственно над функцией executeValidationAndReturnFormElement
:
const checkValidity = (value, validation) => {
let validationObject = {
isValid: true,
errorMessage: ''
};
if (validation) {
if (validation.required) {
validationObject.isValid = value.trim() !== '';
validationObject.errorMessage = validationObject.isValid ? '' : 'Field is required';
}
if (validationObject.isValid && validation.maxLength) {
validationObject.isValid = value.length <= 60;
validationObject.errorMessage = 'Not allowed more than 60 charactes';
}
return validationObject;
}
else {
return validationObject;
}
}
С помощью приведенного выше кода мы проверяем, нужно ли нам вообще проверять ввод. Если его нужно проверить, мы выполняем проверку, но если нет (например, dateOfBirth), мы просто возвращаем тот же объект обратно.
В процессе проверки мы проверяем, имеет ли поле необходимое правило проверки, и проверяем его. Затем, если он все еще действителен, мы проверяем его на соответствие правилу maxLength. Наконец, мы просто возвращаем validationObject
.
Проверка всей формы React
Внутри функции handleChangeEvent
мы вызываем одну дополнительную функцию countInvalidElements
. Итак, давайте реализуем эту функцию чуть ниже функции executeValidationAndReturnFormElement
в файле FormUtility.js
:
export const countInvalidElements = (ownerForm) => {
let countInvalidElements = 0;
for (let element in ownerForm) {
if (!ownerForm[element].valid) {
countInvalidElements = countInvalidElements + 1;
break;
}
}
return countInvalidElements;
}
Эта функция довольно проста. Мы перебираем все элементы внутри ownerForm
. И если мы обнаруживаем какой-либо недопустимый элемент, мы просто увеличиваем переменную countInvalidElements
и выходим из цикла. Наконец, мы возвращаем эту переменную.
Теперь мы можем проверить результаты.
Пустая форма (которую никогда не трогали):
Если мы поместим курсор в поля ввода и оставим:
Другой тип сообщения об ошибке:
Наконец, действительная форма:
Соединяем компонент CreateOwner с редьюсером
Для начала, давайте добавим весь необходимый импорт:
import { connect } from 'react-redux';
import * as repositoryActions from '../../../store/actions/repositoryActions';
import * as errorHandlerActions from '../../../store/actions/errorHandlerActions';
Затем давайте создадим функцию mapStateToProps
под компонентом:
const mapStateToProps = (state) => {
return {
showSuccessModal: state.repository.showSuccessModal,
showErrorModal: state.errorHandler.showErrorModal,
errorMessage: state.errorHandler.errorMessage
}
}
После этого нам нужно создать функцию mapDispatchToProps
ниже mapStateToProps
:
const mapDispatchToProps = (dispatch) => {
return {
onCreateOwner: (url, owner, props) => dispatch(repositoryActions.postData(url, owner, props)),
onCloseSuccessModal: (url, props) => dispatch(repositoryActions.closeSuccessModal(props, url)),
onCloseErrorModal: () => dispatch(errorHandlerActions.closeErrorModal())
}
}
Затем изменим инструкцию export
:
export default connect(mapStateToProps, mapDispatchToProps)(CreateOwner);
Затем, мы собираемся добавить наши модальные компоненты под тегом FormGroup
, но все еще внутри тега Well
:
<SuccessModal show={this.props.showSuccessModal}
modalHeaderText={'Success message'}
modalBodyText={'Action completed successfully'}
okButtonText={'OK'}
successClick={() => this.props.onCloseSuccessModal('/owner-List', { ...this.props })} />
<ErrorModal show={this.props.showErrorModal}
modalHeaderText={'Error message'}
modalBodyText={this.props.errorMessage}
okButtonText={'OK'} closeModal={() => this.props.onCloseErrorModal()} />
И добавим операторы импорта:
import SuccessModal from '../../../components/Modals/SuccessModal/SuccessModal';
import ErrorModal from '../../../components/Modals/ErrorModal/ErrorModal';
SuccessModal
вызывает свойство onCloseSuccessModal
из функции mapDispatchToProps
. Более того, ErrorModal
вызывает свойство onCloseErrorModal
из функции mapDispatchToProps
. Оба эти свойства являются функциями диспетчеризации, которые не реализованы. Так что это то, что нам нужно исправить.
Изменение действия и файлов Reducer
Нам нужно изменить наши файлы, добавив дополнительные функции для закрытия модальных компонентов успешной отправки и ошибки.
Давайте добавим еще два типа действий в файл ActionTypes.js
:
export const CLOSE_ERROR_MODAL = 'CLOSE_ERROR_MODAL';
export const CLOSE_SUCCESS_MODAL = 'CLOSE_SUCCESS_MODAL';
Затем давайте изменим файл repositoryActions.js
, добавив функцию closeSuccessModal
:
export const closeSuccessModal = (props, url) =>{
return {
type: actionTypes.CLOSE_SUCCESS_MODAL,
props: props,
url: url
}
}
Нам также нужно изменить файл repositoryReducer.js
:
case actionTypes.CLOSE_SUCCESS_MODAL:
return executeCloseSuccessModal(state, action)
const executeCloseSuccessModal = (state, action) => {
action.props.history.push(action.url);
return {
...state,
showSuccessModal: false
}
}
Мы закончили с модальным окном успешной отправки, давайте сделаем то же самое для модального окна ошибки.
Во-первых, давайте изменим файл errorHandlerActions.js
, добавив новую функцию:
export const closeErrorModal = () => {
return {
type: actionTypes.CLOSE_ERROR_MODAL
}
}
Затем изменим файл errorHandlerReducer.js
:
case actionTypes.CLOSE_ERROR_MODAL:
return executeCloseErrorModal(state, action);
const executeCloseErrorModal = (state, action) => {
return{
...state,
showErrorModal: false,
errorMessage: ''
}
}
Теперь все, что нам нужно сделать, это отправить запрос POST из компонента CreateOwner.
Обработка запроса POST
Внутри тега Form
есть событие onSubmit
, которое указывает на функцию createOwner
. Давайте реализуем эту функцию ниже функции handleChangeEvent
:
createOwner = (event) => {
event.preventDefault();
const ownerToCreate = {
name: this.state.ownerForm.name.value,
address: this.state.ownerForm.address.value,
dateOfBirth: this.state.ownerForm.dateOfBirth.value
}
const url = '/api/owner';
this.props.onCreateOwner(url, ownerToCreate, { ...this.props });
}
Ниже этой функции нам нужно добавить еще одну функцию для функциональности кнопки Отмена:
redirectToOwnerList = () => {
this.props.history.push('/owner-List');
}
Теперь мы можем проверить результаты:
В случае возникновения ошибки с кодом состояния, отличным от 404 или 500:
Заключение
Прочитав этот пост, вы узнали:
- Как обработать событие onChange в поле ввода
- Как проверить нашу динамически созданную форму
- Как использовать ранее созданные компоненты модального окна
- Способ обработки POST-запроса
Спасибо, что прочитали статью, и я надеюсь, что вы нашли в ней что-то полезное.
В следующей части этой серии мы собираемся узнать, как обрабатывать PUT-запросы. Кроме того, мы собираемся использовать различные хуки жизненного цикла в React и узнать, как обновить наше состояние с помощью измененных данных с сервера.