تقویم شمسی ری اكت و اعتبارسنجی فرم

سلام دوستان

حدود چند روزی در گیر این بودم که چطور در ریاکت از تقویم شمسی استفاده کنم، راه حل ساده بود اما مشکل از اون جایی به وجود اومد که نیاز بود فیلد اجباری باشه.

خوب راه حل ساده تقویم شمسی ، استفاده از Date Picker هست که خیلی از پکیج هارو تست کردم اما... قبل از این مبحث بزارید فیلد اجباری رو بگم.



برای فیلد اجباری از react hook form استفاده کردم که واقعا عالی هست.

روش استفاده به شکل زیر هست?

import React , {useState , useEffect} from 'react';
import { useForm } from &quotreact-hook-form&quot

function Main(){
const { register , handleSubmit, errors } = useForm();
const errorsMassage = <p className=&quoterrors-massage&quot>اطلاعات را وارد نمایید</p>
const  = data => {
const token = localStorage.getItem(&quottoken&quot)
addSkillData({
newItem:  {
&quottitle&quot : data.title,
&quotexpense&quot : data.expense,
&quotstartDate&quot : data.startDate,
},
config : {
headers : {
&quotAuthorization&quot : `Bearer ${token}
}}})};

return (<>
<form ={handleSubmit()}>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>عنوان</label>
<input className=&quotform-control&quot id=&quotaddskill-title&quot
name=&quottitle&quot ref={register({ required: true })} />
{errors.title && errorsMassage}
</div>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>میزان هزینه</label>
<input type=&quottext&quot className=&quotform-control&quot id=&quotaddskill-expense&quot
name=&quotexpense&quot ref={register({ required: true })} />
{errors.expense && errorsMassage}
</div>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>تاریخ شروع</label>
<input type=&quotdate&quot className=&quotform-control&quot id=&quotaddskill-start-date&quot
name=&quotstartDate&quot ref={register({ required: true })} />
{errors.startDate && errorsMassage}
</div>
<input className=&quotbtn btn-primary btn-user btn-block&quot type=&quotsubmit&quot value=&quotثبت&quot />
</form>
</>
)}

خوب در بالا همان طور که می‌بینید در هر input از اتریبیوتی به نام ref استفاده کرده تا مقادیر را علاوه بر ارسال به استیت، اعتبار سنجی هم کنه و در نهایت مقادیر در تابع که به handleSubmit در تگ اصلی فرم در دسترس ما هستند.



حالا من در همین شرایط از دیتا پیکر استفاده کردم مثل زیر ?

import React , {useState , useEffect} from 'react';
import { useForm } from &quotreact-hook-form&quot
import { DatePicker } from &quotdavood-react-persian-datepicker&quot

function Main(){
const { register , handleSubmit, errors } = useForm();
const errorsMassage = <p className=&quoterrors-massage&quot>اطلاعات را وارد نمایید</p>
const  = data => {
const token = localStorage.getItem(&quottoken&quot)
addSkillData({
newItem:  {
&quottitle&quot : data.title,
&quotexpense&quot : data.expense,
&quotstartDate&quot : data.startDate,
},
config : {
headers : {
&quotAuthorization&quot : `Bearer ${token}`
}
}})};

return (<>
<form ={handleSubmit()}>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>عنوان</label>
<input className=&quotform-control&quot id=&quotaddskill-title&quot
name=&quottitle&quot ref={register({ required: true })} />
{errors.title && errorsMassage}
</div>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>میزان هزینه</label>
<input type=&quottext&quot className=&quotform-control&quot id=&quotaddskill-expense&quot
name=&quotexpense&quot ref={register({ required: true })} />
{errors.expense && errorsMassage}
</div>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>تاریخ شروع</label>
<input type=&quothidden&quot className=&quotform-control&quot id=&quotaddskill-start-date&quot
name=&quotstartDate&quot ref={register({ required: true })} />
<DatePicker />
{errors.startDate && errorsMassage}
</div>
<input className=&quotbtn btn-primary btn-user btn-block&quot type=&quotsubmit&quot value=&quotثبت&quot />
</form>
</>
)}

همان طور که مشخص هست ، سعی داشتم input تاریخ میلادی را hidden کنم و تاریخ خروجی DatePicker را به value اینپوت پاس بدم که موفق هم شدم ( بدون استفاده از queryselector ) اما دیگه ref اجرا نمیشد و ارور عمل نمیکرد.

اینجا بود که یکم کلافه شدم و با پرس و جو چند روزه ای که داشتم به یک جواب بسیار شیک رسیدم.




ما در react-hook-form یک متد داریم به نام Controller که اگر در جایی امکان استفاده مستقیم خود input نبود یا ref در دسترس نبود میشه ازش استفاده کرد.

روش استفاده به شکل زیر هست ?

import React , {useState , useEffect} from 'react';
import { useForm , Controller } from &quotreact-hook-form&quot
import { DatePicker } from &quotdavood-react-persian-datepicker&quot

function Main(){
const { register , handleSubmit, errors , control } = useForm();
const errorsMassage = <p className=&quoterrors-massage&quot>اطلاعات را وارد نمایید</p>
const  = data => {
const token = localStorage.getItem(&quottoken&quot)
let date = moment(data.startDate).format('YYYY/M/D')
addSkillData({
newItem:  {
&quottitle&quot : data.title,
&quotexpense&quot : data.expense,
&quotstartDate&quot : date,
},
config : {
headers : {
&quotAuthorization&quot : `Bearer ${token}`
}
}})};

return (<>
<form ={handleSubmit()}>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>عنوان</label>
<input className=&quotform-control&quot id=&quotaddskill-title&quot
name=&quottitle&quot ref={register({ required: true })} />
{errors.title && errorsMassage}
</div>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>میزان هزینه</label>
<input type=&quottext&quot className=&quotform-control&quot id=&quotaddskill-expense&quot
name=&quotexpense&quot ref={register({ required: true })} />
{errors.expense && errorsMassage}
</div>
<div className=&quotform-group col-lg-4 col-md-12&quot>
<label className=&quotmr-1&quot htmlFor=&quot&quot>تاریخ شروع</label>
<Controller
control={control}
name=&quotstartDate&quot
rules={{ required: true }}
defaultValue={moment(skillEditingData.startDate)}
render={({on4Change, on5Blur, va6lue }) => (
<DatePicker
calendarStyles={styles}
inputFormat=&quotjYYYY/jM/jD&quot
v1alue={va4lue}
o2nBlur={on6Blur}
o3nChange={on5Change}
/>
)}
/>
{errors.startDate && errorsMassage}
</div>
<input className=&quotbtn btn-primary btn-user btn-block&quot type=&quotsubmit&quot value=&quotثبت&quot />
</form>
</>
)}

در Controller به جای ref آمده از rules استفاده کرده و گفته در render هر آنچه دوست داری رندر کن فقط onChang1e, onBlu2r, valu3e هارو پاس بده بهش و تمام. ( اعداد به خاطر اينه كه ويرگول كاراكتر هاي مشابه رو حذف ميكنه ،‌شما حتما پاک کنید )



و در آخر منابع رو هم بررسی کنیم:

برای DatePicker از https://www.npmjs.com/package/davood-react-persian-datepicker استفاده کردم البته آن زمانی که داشتم پکیج های مختلف رو تست میکردم تمرکزم روی ref بود ، احتمال زیاد با این خاصیت Controller راحت میشه از هر پکیج دیگه ای استفاده کرد.
برای Controller هم https://react-hook-form.com/api/#Controller را بررسی کنید.
و در نهایت خروجی که DatePicker بهتون میده رو به https://github.com/jalaali/moment-jalaali بدید به شکل زیر ?
let date = moment(data.startDate).format('YYYY/M/D') //میلادی
let dateJalali = moment(data.startDate).format('jYYYY/jM/jD') //شمسی

امیدوارم مورد استفاده قرار گرفته باشه

سوالی داشتید حتما بپرسید