تعامل و انتقال اطلاعات بین کامپوننت‌ها در Angular – بخش اول
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: سه دقیقه

یکی از مواردی که در پیاده سازی برنامه‌های «تا حدودی پیچیده» به آن برخورد می‌کنیم، نحوه تعامل و نقل و انتقال اطلاعات مشترک بین کامپوننت‌ها و سرویس‌‌ها می‌باشد. به عنوان مثال صفحه‌ای را در نظر بگیرید که قرار است اطلاعات یک مشتری را نمایش دهد. این اطلاعات شامل اطلاعات شخص و اطلاعات آدرس او می‌باشد. برای داشتن کامپوننت‌هایی با قابلیت استفاده‌ی مجدد، اطلاعات شخص و اطلاعات آدرس را به عنوان دو کامپوننت مستقل در نظر گرفته و پیاده سازی می‌کنیم. تامین اطلاعات این دو کامپوننت حداقل به دو شکل زیر قابل پیاده سازی خواهد بود. 

  1. تامین اطلاعات از طریق کامپوننت پدر و انتساب اطلاعات به کامپوننت‌های فرزند جهت نمایش
  2. تامین اطلاعات به صورت توکار و توسط خود کامپوننت فرزند 

به جهت کپسوله سازی هرچه بیشتر و همچنین کاهش کدهای تکراری، مورد دوم پیشنهاد می‌شود. در این حالت کامپوننت پدر بایستی شناسه مشتری مورد نظر را به کامپوننت فرزند ارسال کند تا کامپوننت فرزند بر اساس این شناسه، اطلاعات مشتری را واکشی و نمایش دهد. در این مثال انتقال اطلاعات از کامپوننت پدر به فرزند جهت ارسال شناسه مشتری ضروری است. همچنین در مواردی نیز ممکن است کامپوننت فرزند اطلاعات و رخدادهایی را به کامپوننت پدر ارسال کند. مثلا کامپوننت «نمایش اطلاعات شخص» قرار است بعد از واکشی اطلاعات، «حقیقی» یا «حقوقی» بودن شخص را به کامپوننت پدر جهت نمایش عنوان مناسب اطلاع دهد. 

در کل، جهت نقل و انتقال اطلاعات مشترک و تعامل بین کامپوننت‌ها، به چند روش زیر می‌توان اقدام کرد:
  1. انتقال اطلاعات از کامپوننت پدر به فرزند از طریق متادیتا Input@
  2. به‌جریان انداختن رخداد از کامپوننت فرزند و گرفتن آن از طریق کامپوننت پدر
  3. تعامل کامپوننت پدر و فرزند از طریق template reference variable
  4. فراخوانی کامپوننت فرزند از کامپوننت پدر به کمک ViewChild@
  5. ارتباط کامپوننت پدر و فرزند از طریق سرویس 
مثال بالا یک مورد بسیار ساده در جهت تفهیم اجبار نقل و انتقال اطلاعات بین کامپوننت‌ها بود. مطمئنا در برخی موارد پیچیده‌تر، حتی با به اشتراک گذاری اطلاعات بین کامپوننت‌ها لازم است پیاده سازی یک رخداد کامپوننت فرزند را به پدر آن واگذار کنیم. در ادامه تمامی این روش‌ها را مورد برسی قرار خواهیم داد. 

نکته: تمامی مثالهای ذکر شده در ادامه تنها در جهت توضیح مفهوم بوده و در برخی موارد گزینه مناسبی جهت پیاده سازی در برنامه‌های واقعی نیستند. 

انتقال اطلاعات از کامپوننت پدر به فرزند از طریق متادیتای Input@
فرض کنید کامپوننت CustomerInfoComponent را داریم که هم نمایش اطلاعات و هم دریافت اطلاعات مشتری را برعهده دارد (در حالت نمایشی به عنوان مثال قرار است تگ input را به صورت readOnly نمایش دهد). کامپوننت پدر تصمیم می‌گیرد که این کامپوننت به چه صورتی ظاهر شود. برای اینکار لازم است متغیری را در کامپوننت CustomerInfoComponent تعریف کنیم که از طریق کامپوننت پدر (استفاده کننده) قابل تنظیم و مقدار دهی باشد. برای این کار کافی است قبل از تعریف متغیر، از متادیتای Input@ به شکل زیر استفاده کنیم:
import { Component, OnInit, Input} from '@angular/core';

@Component({
    selector: 'app-customer-info',
    templateUrl: './customer-info.component.html',
    styleUrls: ['./customer-info.component.css']
})
export class CustomerInfoComponent implements OnInit {

    @Input() FormIsReadOnly: boolean;

    constructor() { }

    ngOnInit() {
    }
}
به همین راحتی. حالا هنگام استفاده از کامپوننت و ارسال مقدار به کامپوننت به شکل زیر عمل می‌کنیم:
<app-customer-info FormIsReadOnly="{{true}}"></app-customer-info>


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

<app-customer-info FormIsReadOnly="true"></app-customer-info>
مقدار منتسب به متغیر FormIsReadOnly به صورت رشته خواهد بود (یعنی مقدار "true"). همچنین برای انتساب یک متغیر به FormIsReadOnly باید به شکل زیر عمل کرد (با این فرض که booleanVariable به صورت یک متغیر از نوع boolean در کامپوننت پدر تعریف شده است): 
<app-customer-info [FormIsReadOnly]="booleanVariable"></app-customer-info>
در این صورت با تغییر متغیر booleanVariable در کامپوننت پدر، کامپوننت فرزند متوجه تغییر خواهد شد ولی برعکس این مورد صادق نیست. یعنی هر تغییری در متغیر FormIsReadOnly در کامپوننت فرزند، باعث تغییر مقدار booleanVariable نخواهد شد. این بدان معنی است که انقیاد انجام گرفته به صورت یک طرفه و از سمت منبع داده (data source) به کامپوننت فرزند است. 
ادامه دارد/