پیاده سازی Control Value Accessor در انگولار

اجزای شناخته شده فرم ها مانند input، checkbox و ... اجزای استانداردی هستند که معمولا مدل پیاده سازی شده ای در کتابخانه هایی مانند angular material دارند. بعضی موقع ها طراح فیلدی طراحی میکنه که با فیلدهای معمول و استاندارد تفاوت داره. پیچیده تره و نیاز به یک کامپوننت خاص داره.اینترفیس ControlValueAccessor در انگولار به ما این امکان رو میده که با این کامپوننت های خاص مانند یک فیلد فرم ارتباط برقرار کنیم. به کمک CVA میتونیم بین مدیریت فرم و DOM element ها ارتباط برقرار کنیم و رفتارهای فرم مانند یک کامپوننت رو از کامپوننت بالادستش به روشی استاندارد و یکسان پنهان کنیم.در این مقاله میخوایم یک کامپوننت custom درست کنیم که شامل یک input هست و ControlValueAccessor رو براش پیاده کنیم. چهار بخش برای این مقاله در نظر گرفته شده:ساخت کامپوننت نمونهپیاده سازی ControlValueAccessorاتصال به روش two way bindingاتصال به روش reactive formقدم اول: ساخت کامپوننت نمونهاینجا نحوه ساخت و استفاده از کامپوننت های standalone رو کامل توضیح دادم. اگر با کامپونت های standalone آشنایی نداری یا نیازی به مرورشون داری، میتونی مطالعه کنی و ببینی کجا باید این کامپوننت رو برای استفاده معرفی کنی.اگر نمیخوای از کامپوننت standalone استفاده کنی، یادت باشه که همه import های داخل کامپوننت رو ببری به ngModule مربوطه ش اضافه کنی و کامپوننت رو به لیست declaration های ماژول ngModule اضافه کنی.با اجرای دستور زیر یک کامپوننت میسازیم به اسم custom input که standalone هست.داخل src/app یک دایرکتوری ساخته میشه به اسم custom-input:محتوای فایل custom-input.component.ts به صورت زیر هست:داخل تمپلت app.component.ts کد زیر رو اضافه میکنیم:و می بینیم که کامپوننت کار میکنه:داخل تمپلت کامپوننت ( میتونیم تمپلت رو به خاطر کوچکیش ببریم داخل annotation کامپوننت‌ تعریف کنیم) یک input text تعریف میکنیم:و خروجی نهایی به صورت زیر مشاهده میشه:وقتشه بریم سراغ پیاده سازی Value Accessorقدم دوم: ایجاد دسترسی به VALUE_ACCESSORبرای اینکه کامپوننت ما بتونه به VALUE_ACCESSOR دسترسی پیدا کنه و بعدا بتونه تمپلت رو آپدیت کنه و ngModel رو bind کنه و مقدار فعلی رو به صورت خروجی بده، داخل component annotation بخش providers تنظیمات لازم رو ست میکنیم:و بعدش ControlValueAccessor رو پیاده سازی میکنیم. برای این کار نیاز دارید که این متدها و متغیرها رو پیاده سازی کنید:متد : یک callback function که برای تغییرات UI رجیستر میشود.متد onTouch : یک callback function که برای تاچ کامپوننت رجیستر میشود.یک setter بنام value: توسط ngModel استفاده میشود.متد writeValue: مقدار جدید متغیر را روی element می نویسد.متد registerOnchange: وقتی value در UI تغییر میکند این متد یک callback function را صدا میکند.متد registerOnTouch: وقتی المنت در UI تاچ میشود این متد صدا زده میشود.نحوه پیاده سازی به صورت زیر است:قدم سوم: اتصال به کامپوننت اصلی به روش Two Way Bindingتا اینجا هیچ اتفاقی نیفتاده! وقتشه قدم آخر رو برداریم و از پیاده سازی استفاده کنیم. در اینجا از روش two way binding و در بخش بعدی از روش Reactive Form استفاده میکنیم.برای این کار اول FormsModule رو در کامپوننت import میکنیم:برای کامپوننت هایی که standalone نیستند، این ماژول رو در NgModule مربوطه import میکنیمبعد تمپلت کامپوننت رو به صورت زیر تغییر میدیم:داخل app.component.ts یک متغیر تعریف میکنیم تا مقدار مربوط به custom input رو نگهداری کنیم:اگر لازمه ( قبلا انجام ندادیم ) ماژول NgForms رو به ماژول مربوط به کامپوننت استفاده کننده از custom input اضافه میکنیم. اینجا من به app.module.ts اضافه کردم.بعد از اضافه کردن متغیر customInput و ماژول NgForms ، به صورت زیر از کامپوننت استفاده میکنیم:میتونیم یک خروجی هم بگذاریم که نتیجه رو ببینیم:نتیجه رو میتونیم به راحتی مشاهده کنیم:قدم چهارم: اتصال به کامپوننت اصلی به روش Reactive Formتقریبا شبیه قدم قبلیه. اول ماژول ReactiveFormsMudule رو به کامپوننت اضافه میکنیم.برای کامپوننت هایی که standalone نیستند، این ماژول رو در NgModule مربوطه import میکنیمبعد یک FormControl به کامپوننت اضافه میکنیم. من اینجا اسمش رو گذاشتم customControl:این کد رو در NgOnInit یا constructor اضافه میکنیم تا تغییرات costum control رو به بیرون درز بدیم:حالا custom control رو به input در تمپلت اضافه میکنیم:وقتشه که توسط FormBuilder یک فرم در کامپوننت استفاده کننده بسازیم:حالا form control مربوطه رو به کامپوننت مون پاس میدیم:خروجی مورد نظر ما آماده ست:نتیجهالان یک کامپوننت دارم که مثل یک input در فرم رفتار میکنه. حالا در این کامپوننت رفتارهای مورد نظر UI Designer در بخش نمایش به کاربر رو به راحتی پیاده سازی میکنم.الان چه به روش two way binding و چه به روش reactive form میتونیم فیلدهای خاص طراح رو در سیستم توسعه بدیم.موفق باشید :)