در ادامه قسمت قبلی، ما قصد داریم اعتبارسنجی را در form های React پیاده سازی کنیم و با ارسال یک درخواست POST به سمت سرور NET Core Web API. خود، یک موجودیت owner جدید را ایجاد کنیم.
در کامپوننت CreateOwner، ما تابع ()handleChangeEvent را به کامپوننت Input
پاس میدهیم. ما میخواهیم از این تابع برای فعال کردن binding دوطرفه و اعتبارسنجی فیلدهای input خود استفاده کنیم. بنابراین پیاده سازی و ارسال درخواست POST مقصود ما در این مقاله میباشد.
اگر میخواهید تمام دستورالعملهای پایه و راهنمای کامل برای آموزش سریالی NET Core. را ببینید، این لینک را بررسی کنید: دستورالعملهای کار با NET Core.
این مقاله، قسمتی از مجموعه آموزشی زیر میباشد:
- آماده سازی پروژه و ایجاد component ها
- Navigation و مسیریابی (Routing)
- Axios ،HTTP و Redux
- Lazy Loading و HOC Component
- مدیریت خطا و component های اضافی
- ایجاد form داینامیک و component های modal
- اعتبارسنجی Form و Handle کردن درخواست Post
- مدیریت درخواست PUT
- مدیریت درخواست DELETE
اگر میخواهید تمام دستورالعملهای پایه و راهنمای کامل برای آموزش سریالی React را ببینید، به این لینک مراجعه کنید: مقدمه معرفی آموزش سریالی React
برای بررسی قسمت قبل، به این لینک مراجعه کنید: تنظیم Form داینامیک
جهت دانلود سورس بر روی این لینک کلیک کنید: سری آموزشی React – قسمت 7
این پست به قسمتهای زیر تقسیم میشود:
- Handle کردن OnChange Event با تابع handleChangeEvent
- ایجاد Function های اضافی برای اعتبارسنجی React Form
- اعتبارسنجی کامل Form در React
- اتصال کامپوننت CreateOwner با Reducer
- اصلاح Action و فایلهای Reducer
- نتیجه گیری
Handle کردن OnChange Event با تابع handleChangeEvent
در حال حاضر، اگر ما هرچیزی را داخل فیلدهای input تایپ کنیم، هیچ اتفاق خاصی نمی افتد. به این دلیل است که در فایل InputConfiguration.js ما، تمام ویژگیهای “value” برای همه ورودیها بر روی رشتههای خالی تنظیم شدهاند (به جز datePicker، که تابع ()moment را میپذیرد که همیشه تاریخ جاری را بر روی آن اعمال میکند). مهمتر از آن این است که ما هرگز ویژگی value
را در داخل آبجکت configuration تغییر نداده ایم، همینطور فیلدهای input خالی را.
ما میخواهیم با اجرای تابع handleChangeEvent این مشکل را برطرف کرده و یک اعتبارسنجی اضافه کنیم.
پس اجازه دهید تا فایل CreateOwner.js را با اضافه کردن تابع handleChangeEvent
در زیر componentWillMount
lifecycle hook اصلاح کنیم:
1 2 3 4 5 6 7 8 |
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 }) } |
این function دو پارامتر میگیرد. پارامتر event
که مقدار فیلدهای input ما را در خود نگه میدارد (نه فقط مقدار، اما مقدار برای ما مهمترین است) و پارامتر id
که ما قصد داریم یکی از key های آبجکت configuration را به آن پاس دهیم (name ،address یا dateOfBirth).
ما اینجا داریم ownerForm
را از state کپی عمیق میگیریم و سپس تنظیمات input تغییر یافته فعلی را با فراخوانی تابع executeValidationAndReturnFormElement
به روز میکنیم. بعد از اعتبارسنجی، ما تعداد فیلدهای نامعتبر را بدست می آوریم و اگر فیلد نامعتبری وجود داشت، form ما به عنوان form نامعتیر mark میشود. در آخر، ما state را به روز میکنیم.
ایجاد Function های اضافی برای اعتبارسنجی React Form
ما در کد بالا، تابع های executeValidationAndReturnFormElement و countInvalidElements را داریم اما آنها هنوز ایجاد نشده اند.
پس بریم تا آنها را ایجاد کنیم.
بیایید فایل FormUtility.js را اصلاح کنیم:
1 2 3 4 5 6 7 8 9 10 11 12 |
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 را با استفاده از یک عملگر سه جانبه ( ternary operator) پر میکنیم (اگر کاربر ورودی dateOfBirth
را تغییر دهد، سپس event
همان value ما میباشد، اما برای هر فیلد ورودی دیگر، event
آبجکتی است که ویژگی target
را دارد که این ویژگی، ویژگی value
را در خود نگه میدارد). علاوه بر این، ما میخواهیم ویژگی touched را برای کنترل خود set کنیم و سپس مقدار و قوانین اعتبارسنجی را به فرآیند اعتبارسنجی ارسال کنیم. پس از انجام فرآیند، نتایج را ذخیره می کنیم. در نهایت، formElement را با تمام تغییرات برمی گردانیم.
پیاده سازی تابع CheckValidity
پس تابع checkValidity
را درست بالای تابع executeValidationAndReturnFormElement
پیاده سازی میکنیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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; } } |
با کد بالا، ما بررسی میکنیم که آیا ما اصلا باید input را اعتبارسنجی کنیم یا خیر. اگر نیاز به اعتبارسنجی باشد سپس اعتبار سنجی را برای آن انجام میدهیم، اما اگر نیاز نداشته باشد (مانند dateOfBirth)، فقط همان خود object را دومرتبه برمیگردانیم.
در این فرآیند اعتبار سنجی، بررسی می کنیم که آیا فیلد مورد نظر، قانون required validation را دارد و در صورت داشتن آن را اعتبارسنجی می کنیم. سپس اگر هنوز معتبر باشد، در برابر قانون maxLength نیز آن را اعتبار سنجی می کنیم. در نهایت، ما فقط validationObject را برمی گردانیم.
اعتبارسنجی کامل Form در React
داخل تابع handleChangeEvent
، ما یک تابع دیگر به نام countInvalidElements را فراخوانی کرده ایم. پس اجازه دهید این تابع را نیز درست پایین تابع executeValidationAndReturnFormElement
در فایل FormUtility.js پیاده سازی کنیم:
1 2 3 4 5 6 7 8 9 10 |
export const countInvalidElements = (ownerForm) => { let countInvalidElements = 0; for (let element in ownerForm) { if (!ownerForm[element].valid) { countInvalidElements = countInvalidElements + 1; break; } } return countInvalidElements; } |
این function کاملا واضح و روشن است. ما اینجا داریم بر روی کل element های درون ownerForm حلقه میزنیم و به محض اینکه یک element نامعتبر را در آن پیدا کردیم، متغیر countInvalidElements
را یک واحد افزایش میدهیم و از حلقه خارج میشویم. در آخر این متغیر را برمیگردانیم.
عالی.
حالا میتوانیم نتایج را بررسی کنیم.
form خالی (که هنوز touche نشده است):
اگر cursor را داخل فیلدهای input خود قرار دهیم و cursor را از روی آن برداریم:
نوع دیگر خطا:
در آخر، form معتبر:
اتصال کامپوننت CreateOwner با Reducer
اول از همه، تمام import های ضروری را اضافه میکنیم:
1 2 3 |
import { connect } from 'react-redux'; import * as repositoryActions from '../../../store/actions/repositoryActions'; import * as errorHandlerActions from '../../../store/actions/errorHandlerActions'; |
سپس تابع
را قسمت پایین component ایجاد میکنیم:mapStateToProps
1 2 3 4 5 6 7 |
const mapStateToProps = (state) => { return { showSuccessModal: state.repository.showSuccessModal, showErrorModal: state.errorHandler.showErrorModal, errorMessage: state.errorHandler.errorMessage } } |
بعد از آن، باید تابع mapDispatchToProps
را زیر mapStateToProps ایجاد کنیم:
1 2 3 4 5 6 7 |
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
را تغییر میدهیم:
1 |
export default connect(mapStateToProps, mapDispatchToProps)(CreateOwner); |
در نهایت، ما میخواهیم component های modal خود را در زیر تگ FormGroup، اما همچنان در داخل تگ Well اضافه کنیم:
1 2 3 4 5 6 7 8 9 10 |
<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 را اضافه میکنیم:
1 2 |
import SuccessModal from '../../../components/Modals/SuccessModal/SuccessModal'; import ErrorModal from '../../../components/Modals/ErrorModal/ErrorModal'; |
SuccessModal
ویژگی onCloseSuccessModal
از تابع mapDispatchToProps
را فراخوانی میکند. علاوه بر این، ErrorModal
، ویژگی onCloseErrorModal
از تابع mapDispatchToProps
را فراخوانی میکند. هردوی این ویژگیها، تابع های dispatch هستند که هنوز پیاده سازی نشده اند. بنابراین این کاری است که باید انجام دهیم.
اصلاح Action و فایلهای Reducer
ما باید فایلهای خود را با افزودن function های دیگر برای بستن component های success modal و error modal تغییر دهیم.
پس دو نوع action دیگر داخل فایل ActionTypes.js اضافه میکنیم:
1 2 |
export const CLOSE_ERROR_MODAL = 'CLOSE_ERROR_MODAL'; export const CLOSE_SUCCESS_MODAL = 'CLOSE_SUCCESS_MODAL'; |
سپس فایل repositoryActions.js را با اضافه کردن تابع closeSuccessModal
تغییر میدهیم:
1 2 3 4 5 6 7 |
export const closeSuccessModal = (props, url) =>{ return { type: actionTypes.CLOSE_SUCCESS_MODAL, props: props, url: url } } |
ما باید فایل repositoryReducer.js را نیز اصلاح کنیم:
1 2 3 4 5 6 7 8 9 10 |
case actionTypes.CLOSE_SUCCESS_MODAL: return executeCloseSuccessModal(state, action) const executeCloseSuccessModal = (state, action) => { action.props.history.push(action.url); return { ...state, showSuccessModal: false } } |
کار ما با success modal تمام شد. حالا همین کار را برای error modal انجام میدهیم.
ابتدا فایل errorHandlerActions.js را با افزودن یک function دیگر اصلاح میکنیم:
1 2 3 4 5 |
export const closeErrorModal = () => { return { type: actionTypes.CLOSE_ERROR_MODAL } } |
سپس فایل errorHandlerReducer.js را اصلاح میکنیم:
1 2 3 4 5 6 7 8 9 10 |
case actionTypes.CLOSE_ERROR_MODAL: return executeCloseErrorModal(state, action); const executeCloseErrorModal = (state, action) => { return{ ...state, showErrorModal: false, errorMessage: '' } } |
حالا تمام کاری که باید انجام دهیم ارسال یک درخواست POST از کامپوننت CreateOwner است.
Handle کردن درخواست POST
onSubmit
event داخل تگ Form
وجود دارد که به تابع createOwner
اشاره میکند. پس اجازه دهید این تابع را زیر تابع handleChangeEvent
پیاده سازی کنیم:
1 2 3 4 5 6 7 8 9 10 11 12 |
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 }); } |
پایین این تابع، ما باید یک تابع دیگر برای عملکرد دکمه Cancel اضافه کنیم:
1 2 3 |
redirectToOwnerList = () => { this.props.history.push('/owner-List'); } |
حالا میتوانیم نتایج را با هم بررسی کنیم:
اگر خطا با کد وضعیت غیر از 404 یا 500 رخ دهد:
نتیجه گیری
با خواندن این مطلب شما یاد گرفتید:
- نحوه handle کردن رویداد onChange در یک فیلد input
- نحوه اعتبارسنجی form داینامیک
- نحوه استفاده از component های پنجره modal ایجاد شده در مقاله قبلی
- شیوه handle کردن درخواست POST
در قسمت بعدی این سری آموزشی، قصد داریم نحوه handle کردن درخواستهای PUT را یاد بگیریم. علاوه بر این، قصد داریم از hook های مختلف lifecycle در React استفاده کرده و نحوه آپدیت کردن state خود با داده های اصلاح شده از سرور را یاد بگیریم.