Decorator های Input و Output و Directive ها در Angular
شناسه پست: 3939
بازدید: 186

decorator های Input و Output در Angular، هنگام برقراری ارتباط بین component های والد و فرزند در برنامه های ما بسیار مهم هستند.

در حین توسعه پروژه، گاهی اوقات ممکن است component های ما بزرگ شده و خواندن آنها دشوار باشد. بنابراین، تقسیم کردن یک component بزرگ به چند component کوچکتر همیشه تصمیم مطلوبی است. علاوه بر این، component های کوچکتر را می توان مجددا در component های دیگر استفاده کرد، بنابراین ایجاد رابطه والد-فرزند، یک ایده بسیار خوبی است. component فرزند به component والد وابسته است و به همین دلیل آنها یک قسمت منسجم را می سازند.

ایجاد component های فرزند با استفاده از decorator های Input و Output در Angular، هدف ما در این پست میباشد.

چکیده

در موقعیت‌هایی که می‌خواهیم محتوایی را از والد به component فرزند ارسال کنیم، باید از دکوراتور Input@ در component فرزند استفاده کنیم تا یک خاصیت اتصال بین آن component ها فراهم کنیم. علاوه بر این، می‌توانیم برخی event ها را در component فرزند داشته باشیم که رفتار آن را در component والد منعکس می‌کند. برای این منظور، ما قصد داریم از دکوراتور Output@ با EventEmitter استفاده کنیم.

برای handle کردن پیام های موفقیت آمیز و پیامهای خطا (غیر از پیامهای 500 یا 404)، ما قصد داریم component های فرزند از نوع modal ایجاد کنیم. ما قصد داریم این component ها را در هر component ای که نیاز به نمایش این نوع پیام ها دارد reuse کنیم. زمانی که می‌خواهیم این نوع از component های reuse خود را ثبت کنیم، ایجاد یک ماژول shared و ثبت و export کردن component های خود در داخل این ماژول روش خوبی میباشد. سپس، با ثبت این ماژول shared در داخل یک ماژولی که مسئول component رده بالاتر است، می‌توانیم از آن component های reusable در هر component سطح بالاتری که می‌خواهیم استفاده کنیم.

Split کردن OwnerDetails با Decorator های Input و Output در Angular

در حال حاضر، کامپوننت OwnerDetails خود را داریم که داده‌های owner و account ها را در صفحه نشان می‌دهد. ما می‌توانیم آن را split کرده و به این ترتیب component خود را تمیزتر و نگهداری آن را آسان‌تر سازیم.

برای انجام این کار، اجازه دهید با ایجاد یک component جدید، کار خود را شروع کنیم:

ما فایل‌های این component را در پوشه owner-details قرار می‌دهیم زیرا قرار است از آن فقط برای استخراج محتوایی از کامپوننت OwnerDetails استفاده کنیم.

حالا فایل owner-accounts.component.ts را اصلاح میکنیم:

ما اینجا یک property از نوع آرایه به نام Account اضافه کردیم و آن را با دکوراتور Input@ مزین کرده ایم.

در مرحله بعد، می‌خواهیم جدولی را که account ها را نشان می‌دهد را از فایل owner-details.component.html کات کرده و آن را با selector از OwnerAccountsComponent جایگزین کنیم:

در اینجا، از انتخابگر app-owner-accounts برای تزریق component فرزند به component والد استفاده می کنیم. همچنین، از ویژگی binding برای pass دادن تمام account ها از آبجکت owner به ویژگی Input accounts@ در component فرزند استفاده می‌کنیم.

پس از آن، می‌توانیم کدی را که از component والد cut کرده ایم را در داخل فایل owner-details.component.html قرار دهیم:

همچنین اینجا می‌توانیم متوجه شویم که دیگر از owner?.accounts در داخل دستور *ngFor استفاده نمی‌کنیم، بلکه فقط از ویژگی accounts استفاده می‌کنیم.

با این وجود، می‌توانیم برنامه خود را اجرا کنیم و اگر به کامپوننت OwnerDetails برویم، همان نتیجه قبلی را خواهیم دید. فقط این بار، ما logic را به داخل دو component جدا کرده ایم.

ارسال Event ها از Component فرزند با استفاده از Output Decorator@

از ساده ترین مثال برای نشان دادن نحوه ارسال event ها از component فرزند به component والد استفاده میکنیم.

برای شروع، میخواهیم مقداری تغییرات داخل OwnerAccountsComponent اضافه کنیم:

ما اینجا از @Ouput decorator به همراه EventEmitter برای ارسال یک event از component فرزند به یک component والد استفاده کرده ایم. همچنین اینجا با درنظر گرفتن یک type برای EventEmitter، تعیین کرده ایم که آن فقط میتواند نوع داده ای Account را ارسال کند. علاوه بر این، یک تابع onAccountClicked ایجاد کرده ایم که این تابع، account را به عنوان ورودی گرفته و تابع emit را برای ارسال این event به component والد فراخوانی میکند.

برای اینکه بتوانیم این تابع onAccountClicked را فراخوانی کنیم، باید فایل owner-accounts.component.html را به این صورت تغییر دهیم:

ما اینجا فقط رویداد click را به ردیف داخل جدول اضافه کردیم.

در نهایت، برای اینکه وقتی روی ردیف‌های account  خود حرکت می‌کنیم، بتوانیم نشانگر ماوس را به صورت cursor نشان دهیم، فایل owner-accounts.component.css را به این صورت تغییر می‌دهیم:

برای اینکه emitter ما کار کند، باید از component والد خود به آن subscribe شویم.

اولین کاری که می‌خواهیم انجام دهیم این است که یک تابع واحد در فایل owner-details.component.ts اضافه کنیم:

و سپس، تنها کاری که باید انجام دهیم این است که می‌خواهیم همه اینها را در فایل owner-details.component.html به یکدیگر connect کنیم:

در اینجا، رویدادی را با همان نام ویژگی Output@ خود در component فرزند ایجاد می کنیم و یک تابع printToConsole لوکال را به آن اختصاص می دهیم. همچنین، اینجا ما از event$ به عنوان یک پارامتر برای پذیرش آبجکت emit شده از component فرزند استفاده کرده ایم.

در این مرحله، می‌توانیم اپلیکیشن خود را اجرا کنیم، و هنگامی که به کامپوننت OwnerDetails (با کلیک روی دکمه Details) برویم، می‌توانیم ببینیم که به محض کلیک روی هر account، پیامی در کنسول، log خواهد شد.

ایجاد ماژول Shared

همانطور که گفتیم، برای component های اشتراکی، ایجاد یک ماژول Shared همیشه شیوه خوبی است. بنابراین، اجازه دهید با ایجاد این ماژول Shared در پوشه shared کار خود را شروع کنیم:

این دستور همچنین SharedModule را به داخل فایل include ،owner.module.ts خواهد کرد:

سپس فایل shared.module.ts را اصلاح میکنیم:

Error Modal Component

این دستور AngularCLI را برای ایجاد یک error modal component اجرا میکنیم:

این دستور علاوه بر ایجاد فایل های component، یک component جدید را به داخل ماژول import ،shared می کند. اما باید آن را به صورت دستی export کنیم:

در آرایه exports، ما component خود را export می کنیم. علاوه بر این، از آنجایی که ما می خواهیم کامپوننت modal را از ngx-bootstrap استفاده کنیم، آن را با استفاده از تابع forRoot به داخل آرایه imports تزریق می کنیم.

حالا فایل error-modal.component.ts را اصلاح میکنیم:

در اینجا ما سه ویژگی داریم که می خواهیم در قسمت HTML این component استفاده کنیم. همچنین کلاس BsModalRef را داخل سازنده inject می کنیم. ما از آن در فایل HTML نیز استفاده خواهیم کرد، بنابراین آن را public در نظر خواهیم گرفت.

با اصلاح فایل error.modal.component.html به کار خود ادامه میدهیم:

این فقط یک فایل HTML ساده است که از string interpolation برای اضافه کردن متن برای header، body و button استفاده می کند. علاوه بر این، ما می‌توانیم اینجا ببینیم که چگونه از bsModalRef، که در داخل سازنده تزریق کرده‌ بودیم، برای فراخوانی تابع hide، جهت مخفی کردن modal استفاده کرده ایم.

ایجاد Success Modal Component

برای ادامه، یک success modal را به همان روشی که error modal را ایجاد کردیم ایجاد میکنیم:

ما باید کامپوننت success-modal را از فایل export ،shared.module.ts کنیم:

سپس، فایل success-modal.component.ts خود را اصلاح میکنیم:

هنگامی که action های create ،update یا delete را با موفقیت انجام دادیم، از کامپوننت success استفاده می‌کنیم و با فشردن دادن دکمه OK، کاربر را به کامپوننت owner-list ریدایرکت می‌کنیم. به همین دلیل است که از کلاس EventEmitter استفاده می کنیم. همچنین، این بار از bsModalRef به صورت private استفاده می کنیم، زیرا فقط در داخل فایل ts. از آن استفاده خواهیم کرد.

در نهایت، فایل success-modal.component.html را به این صورت اصلاح میکنیم:

در مقاله بعدی قصد داریم از هر دوی این component های modal استفاده کنیم.

Directive ها

در قسمت آخر این مقاله، ما به شما نشان می دهیم که چگونه از directive ها برای افزودن رفتار اضافی به عناصر در برنامه Angular خود استفاده کنید.

بنابراین، Append directive را در پوشه shared ایجاد میکنیم:

این directive، یک فایل جدید با @Directive decorator و انتخابگر [appAppend] ایجاد می کند. ما از این انتخابگر برای اضافه کردن رفتار اضافی به عناصر داخل کامپوننت OwnerDetails استفاده می کنیم:

همانطور که می بینید، انتخابگر [appAppend] را در هر دو عنصر span اضافه کرده ایم و همچنین، آبجکت owner را به عنوان پارامتر به directive خود ارسال کرده ایم.

حال باید فایل directive را به این صورت اصلاح کنیم:

در اینجا ما دارای خاصیت ownerParam هستیم که آن را با @Input decorator مزین کرده ایم. ما این کار را به منظور پذیرش پارامتر از component والد انجام می دهیم. سپس در داخل سازنده، کلاس های ElementRef و Renderer2 را تزریق می کنیم. ما از کلاس ElementRef برای ارجاع به عنصری استفاده می کنیم که directive خود را روی آن اعمال کرده ایم. علاوه بر این، ما از Renderer2 برای دستکاری عناصر بدون لمس مستقیم DOM استفاده می کنیم. بنابراین، همانطور که می بینید، نیازی به JQuery برای دستکاری عناصر DOM نیست – Angular تمام ابزارهای مورد نیاز را در اختیار ما قرار می دهد.

پس از اصلاح constructor، یک متد lifecycle جدید به نام ngOnChanges اضافه می کنیم. این متد قبل از ngOnInit lifecycle hook و همچنین هر بار که یک یا چند ویژگی input تغییر می کند، فراخوانی می شود. در داخل آن، بررسی می کنیم که آیا ویژگی input ما دارای currentValue پر شده است یا خیر. اگر چنین شد، تعداد account ها را استخراج کرده، از renderer برای ایجاد span و عناصر text جدید استفاده می‌کنیم و آنها را با هم ترکیب می‌کنیم.

در نهایت، ما از همان ویژگی renderer برای ترکیب nativeElement خود با عنصر span جدید ایجاد شده استفاده می کنیم.

اکنون می‌توانیم برنامه‌های خود را اجرا کنیم و پس از navigate کردن به صفحه جزئیات هر کاربر، directive خود را در عمل مشاهده خواهیم کرد:

استفاده از Directive برای اضافه کردن تعداد account ها

می بینیم که اینجا اطلاعات جدیدی را در کنار توضیحات کاربر داریم. برای کاربران مختلف، تعداد account های متفاوتی را دریافت خواهیم کرد.

نتیجه گیری

در این مقاله، هدف از decorator های Input-Output در Angular و اینکه چگونه اطلاعات را بین component های والد و فرزند به اشتراک بگذاریم را یاد گرفتیم. همچنین، ما در مورد ماژول shared و استفاده از directive ها برای افزودن رفتار اضافی به عناصر برنامه Angular صحبت کردیم.

در قسمت بعدی این آموزش گام به گام، قصد داریم کار خود را با ایجاد owner و اعتبارسنجی فرم شروع کنیم.

نویسنده

امید عباسی
من امید عباسی هستم. سالهاست که در زمینه برنامه نویسی با تکنولوژی دات نت فعالیت میکنم و عاشق این هستم که تجربیات و دانش خودم را در این زمینه با دیگران به اشتراک بزارم. خیلی دوست دارم که نظر و انتقاد خودتون رو در مورد این نوشته برای من بنویسید تا بتونم در آینده، مطالب بهتر و ارزشمندتری را برای شما فراهم کنم. در صورت داشتن هرگونه سوال هم در قسمت دیدگاه ها میتونید با بنده در ارتباط باشید