کار با کامپوننت‌ها و ارسال داده‌ها در انگولار ۲ - بخش ۱-۳

23 شهریور 1399
3-angular2main

با بررسی بخش‌های گذشته به این نتیجه رسیدیم که ساخت و اجرای یک کامپوننت با دستور angular-cli به راحتی امکان پذیر است. در این کامپوننت که با تگهای مشخصی داخل قالب مورد استفاده قرار می‌گیرد، مجموعه‌ی ۴ فایل وجود دارد که با پسوندهای ts, html‌ و css تفکیک شده‌اند. سپس با اعمال تغییرات در قالب اصلی app.component.html و hello-world.component.htmlُ، متن دلخواه خود را به نمایش گذاشتیم. در این بخش قصد داریم مفاهیم داده و ارسال اطلاعات به کامپوننت‌ها در انگولار 2 و در نهایت نمایش آنها در مرورگر را گسترده تر کرده و به دنباله‌ی آموزش‌های قبلی، اطلاعات غنی‌تری از این فریم‌ورک قدرتمند را در اختیار شما قرار دهیم.

اضافه کردن داده به کامپوننت‌ها در انگولار 2

هم‌اکنون کامپوننتی که ایجاد کرده‌ایم تنها یک قالب استاتیک است که از نظر جذابیت و کارایی زیاد موثر نیست. حال فرض کنید نرم‌افزار ما لیستی از اطلاعات کاربران را که شامل نام آنهاست به نمایش می‌گذارد. بنابراین برای دستیابی به اطلاعات موردنظر باید هر کار را به‌صورت جداگانه مورد بررسی قرار دهیم. خب حالا میخواهیم یک کامپوننت جدید برای نمایش نام کاربران ایجاد کنیم. بنابراین مانند بخش ۱-۲ از دستور ng generate برای ایجاد کامپوننت بهره‌مند خواهیم شد:

ng generate component user-item

همواره به این نکته ضروری توجه کنید:‌ برای مشاهده محتویات کامپوننت‌ها در انگولار 2 باید آنها را به قالب اصلی اضافه کنید.

مطابق نکته‌ی بالا تگ app-user-item را به قالب app.component.html اضافه کنید. بسیار عالی! تغییرات کامپوننت برای شما قابل مشاهده خواهد بود. پس به app.component.html رفته و تغییرات زیر را اعمال کنید:

<h1>
    {{title}}

    <app-hello-world></app-hello-world>
    <app-user-item></app-user-item>
</h1>

صفحه مرورگر خود را به آدرس http://localhost:4200 مجددا بارگذاری کنید. طبیعتا باید عبارت user-item works! نمایش داده شود. حال باید تنظیمات و کدهای لازم را برای نمایش اسامی کاربران در UserItemComponent اعمال کرد. برای اینکار از یک ویژگی جدید تحت عنوان name استفاده کنید. با این ویژگی می‌توان این کامپوننت را برای کاربران مختلف مورد استفاده قرار داد. برای اضافه کردن یک اسم، ویژگی جدیدی را درون کلاس UserItemComponent تحت عنوان یک متغییر محلی (Local Variable) با نام name تعریف کنید:

export class UserItemComponent implements OnInit {

  name: string;

  constructor() {
    this.name = "Masoud";
  }

  ngOnInit() {
  }

}

توجه داشته باشید که با اعمال تغییرات بالا دو مشخصه تغییر خواهد کرد:

۱) ویژگی name

در کلاس UserItemComponent یک ویژگی جدید اضافه شد. توجه داشته باشید که این سینتکس ارتباطی با JavaScript ES5 دارد. هنگامی که دستور name: string; نوشته می‌شود، اینطور به نظر می‌رسد که name به عنوان نامی میخواهید برای هر کاربر تنظیم کنید قرار می‌گیرد و از نوع string است.

مشخص کردن نوع اسم یکی از ویژگی‌های TypeScript است و این اطمینان را به شما می‌دهد که تمامی اسامی از نوع string و رشته هستند. بنابراین ویژگی name در تمام نمونه‌های (instances) ایجاد شده از کلاس UserItemComponent ایجاد و قابل دسترس خواهد بود. از طرفی کامپایلر نیز اطمینان دارد که این ویژگی از نوع رشته است.

۲) سازنده

در کلاس UserItemComponent یک سازنده تعریف شده است (یعنی یک تابعی که هنگام ساخت نمونه از این کلاس، اجرا می‌شود). در این سازنده می‌توان به ویژگی name با عبارت this.name دسترسی داشت:

constructor() {
  this.name = "Masoud";
}

هنگامیکه دستور بالا نوشته می‌شود، هرگاه یک UserItemComponent جدید ساخته شود، ویژگی نام برابر "Masoud" خواهد بود.

خروجی گرفتن از قالب

به متغییر محلی تعریف شده در قسمت قبل می‌توان با سینکتس (ساختار) دو کروشه (یا سینتکس سیبیل) به مقدار آن دسترسی داشت. برای مثال:

<p>
	Hello {{ name }}
</p>

در نظر دارید که به template سینتکس جدیدی تحت عنوان {{ name }} اضافه شد. از آنجاکه template به کامپوننت ما محدود می‌شود، name نیز به دارای مقدار this.name (که در اینجا "Masoud" است) اشاره می‌کند.

پس از تغییرات بالا، صفحه مرورگر شما عبارت Hello Masoud را نمایش می‌دهد. به تصویر زیر توجه کنید:

دریافت اطلاعات از کامپوننت‌ها

کار کردن با آرایه‌ها

هم اکنون می‌توان عبارت Hello را با یک اسم نمایش داد. اما فرض کنید می‌خواهید عبارت ثابت Hello را برای تمامی اسامی موجود در کامپوننت نمایش دهید. چه‌کار باید کرد؟

برای تکرار کردن یک ویژگی درون یک قالب، انگولار ۲ دستور NgFor‌ را معرفی کرده است (این دستور با نشانه و علامت *ngFor استفاده می‌شود). هدف از ایجاد دستور *ngFor این است:‌ برای مجموعه‌ای از اشیاء ساخته‌شده، یک تگ و نشانه‌گذاری را تکرار کن!

برای ادامه‌ی آموزش و کار کردن با آرایه‌ها یک کامپوننت جدید دیگری را ایجاد کنید و نام آن را user-list بگذارید. از دستور زیر جهت ساخت این کامپوننت می‌توان بهره برد:

ng generate component user-list

مطابق نکات قبلی در فایل app.component.html تگ جدید app-user-list را جایگزین تگ app-user-item کنید.

<h1>
    {{title}}

    <app-hello-world></app-hello-world>
    <app-user-list></app-user-list>
</h1>

همچنین مشابه مراحل قبل ویژگی name را به کلاس UserListComponent اضافه کنید. با این حال به جای ذخیره کردن یک نام و رشته، باید مجموعه از رشته‌ها را درون یک آرایه قرار داد. یک آرایه در تایپ اسکریپت مانند تمام زبان‌ها برنامه‌نویسی داخل [ ] تعریف می‌شود. بنابراین داریم:

export class UserListComponent implements OnInit {

  names: string[];

  constructor() {
    this.names = ['Masoud', 'Roxo' , 'Shop' , 'Forum'];
  }

  ngOnInit() {
  }

}<code data-mce-bogus="1"></code>

دستور بالا نشان می‌دهد که names شامل آرایه‌ای از رشته‌ها است. مطابق با معیارهای یک آرایه، سازنده نیز تغییر می‌کند که در اینجا this.names مقادیر Masoud, Roxo, Shop‌ و Forum را نمایش می‌دهد. حال وقت آن رسیده که قالب خود را آپدیت و بروزرسانی کنید. برای اینکار ما از دستور *ngFor برای تکرار لیستی از آیتم‌ها و ایجاد یک تگ جدید برای هر یک استفاده می‌کنیم. بنابراین تغییرات جدید در فایل template به صورت زیر خواهد بود:

<ul>
  <li *ngFor="let name of names">Hello {{ name }} </li>
</ul>

قالب را با تگ‌های ul‌ و li و همچنین صفت جدید *ngFor = "let name of names" بروزرسانی کردیم. کاراکتر ستاره (*) و سینتکس let برای شما ممکن است جدید باشد!

بررسی سینتکس *ngFor: به ما می‌گوید که از دستور NgFor برای این نرم‌افزار استفاده کن. شما می‌توانید این دستور را مشابه حلقه for در سایر زبان‌های برنامه‌نویسی درنظر بگیرید.

بررسی عبارت let name of names: ویژگی names به عنوان مجموعه‌ای از اشیاء درون کلاس UserListComponent تعریف شده است. عبارت let name به عنوان یک مرجع و رفرنس معرفی می‌شود. هنگامیکه عبارت let name of names استفاده می‌شود، در واقع به هر المان یک آرایه فرمان ارائه‌ی name ارسال می‌شود.

توجه: برای عبارت let name of names لزومی ندارد که name حتما از نوع names و مفرد باشد، بلکه می‌توانید هر اسمی که مد نظرتان هست را قرار دهید و سپس مقدار آن را فراخوانی کنید. به مثال زیر توجه داشته باشید:

<li *ngFor="let esm of names">Hello {{ esm }} </li>

اما در نظر داشته باشید، عبارت names قابل تغییر نیست و باید دقیقا مشابه آنچه که در کلاس UserListComponent تعریف کرده‌اید، باشد.

پس از ذخیره‌سازی دستورهای بالا و بروزرسانی صفحه مرورگر خود با تصویر زیر روبه‌رو خواهید شد:

نمایش لیستی از اسامی کاربران در انگولار ۲

استفاده کردن از کامپوننت User Item

اگر به یاد داشته باشید یک کامپوننت تحت عنوان UserItemComponent ایجاد کرده بودیم! به جای رندر کردن هر نام درون UserListComponent می‌توان از UserItemComponent تحت عنوان یک کامپوننت فرزند (Child Component) استفاده کرد. و این کار باعث می‌شود به جای تکرار تگ li کامپوننت UserItemComponent برای هر آیتم درون لیست اجرا شود.

برای اجرای اینکار، ۳ مورد ضروری است:

  • تنظیم UserListComponent برای رندر کردن UserItemComponent (در قالب)
  • تنظیم UserItemComponent برای پذیرفتن متغییر اسم یه عنوان یک input یا ورودی
  • تنظیم قالب UserListComponent برای ارسال name به UserItemComponent

این مراحل را به صورت قدم به قدم انجام می‌دهیم.

رندر کردن UserItemComponent

کامپوننت User Item دارای سلکتور app-user-item بود. باید این تگ را به قالب user-list.component.html اضافه کرد. بنابراین به جای تگ li از این تگ استفاده کنید:

<ul>
  <app-user-item *ngFor="let name of names">
  </app-user-item>
</ul>

در نظر داشته باشید که علی‌رغم اضافه کردن تگ app-user-item به‌جای تگ li باید دستور *ngFor همواره وجود داشته باشد چون ما به تکرار نیاز داریم. نکته‌ی دیگری که باید در نظر داشته باشید حذف محتوای درون تگ li‌ است، زیرا می‌خواهیم آن را به تگ app-user-item بسپاریم.

اگر صفحه مرورگر خود را بروزرسانی کنید با تصویر زیر مواجه می‌شوید:

حطای عدم ارسال داده از یک کامپوننت در کامپوننت دیگری

همانطور که مشاهده می‌کنید این دستور باعث می‌شود که تکرار فعال باشد اما تنها یک اسم و آن نیز "Masoud" به نمایش گذاشته شده است. در حالیکه این درست نیست. چون اسم "Masoud" از کامپوننت User Item فراخوانی می‌شود. ما نیاز داریم اطلاعات را به کامپوننت فرزند ارسال کنیم.

بسیار عالی! کامپوننت‌ها در انگولار 2 راهی را برای حل این مشکل مطرح کرده‌اند و آن استفاده از مفسر @input‌ است.

پذیرفتن ورودی‌ها

به یاد دارید که درون UserItemComponent، عبارت داخل سازنده برابر this.name='Masoud'; بود. حال باید تغییراتی را درون این کامپوننت ایجاد کنید:

import {
  Component,
  OnInit,
  Input
} from '@angular/core';

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

  @Input() name: string;

  constructor() {

  }

  ngOnInit() {
  }

}

در کامپوننت مشابه دستور بالا ویژگی نام را به یک مفسر @Input تغییر دادیم. درباره sInput و Outputs در فصل بعدی به تفصیل صحبت خواهیم کرد. اما تا به این جای کار درجریان باشید که این دستور اجازه ارسال یک مقدار از قالب والد (Parent Template) را فراهم می‌کند. برای استفاده کردن از Input کافی‌ست آن را در ابتدای برنامه‌ی خود import کنید. از آنجایی که نمی‌خواستیم مقداری پیش‌فرض را برای ویژگی name درنظر بگیریم، آن را از سازنده حذف کردیم.

ارسال یک مقدار ورودی (Input value)

برای ارسال یک مقدار به کامپوننت‌ها در انگولار 2 از براکت [ ] درون قالب استفاده کنید:

<ul>
  <app-user-item 
    *ngFor="let name of names"
    [name] = "name">
  </app-user-item>
</ul>

همانگونه که مشاهده کدردی برای ارسال اطلاعات به کامپوننت فرزند از تگ [name] = "name" استفاده کردیم. در انگولار ۲، هنگامیکه یک صفت داخل براکت (مثلا [roxo]) قرار می‌گیرد، نشان‌دهنده‌ی ارسال یک مقدار به یک input با نام roxo درون کامپوننت است. در این مثال name که در سمت راست قرار گرفته از let name‌ موجود در ngFor استخراج شده است. درنظر بگیرید اگر مقدار name را به individualUserName تبدیل کنیم، کد بالا به شکل زیر تغییر خواهد کرد:

<ul>
  <app-user-item
    *ngFor="let individualUserName of names"
    [name] = "individualUserName">
  </app-user-item>
</ul>

همچنین بخش [name] در قسمت UserItemComponent معرفی شده است. درنظر داشته باشید که داخل Input یک رشته ارسال نمی‌شود بلکه مقدار individualUserName برای هر names ارسال خواهد شد.

درباره Inputs و outputs در فصل آینده به تفصیل صحبت خواهیم کرد. هم اکنون، باید بدانید:

  • تکرارهایی روی names انجام شد
  • یک کامپوننت تحت عنوان UserItemComponent برای هر المان names ساخته شد
  • ارسال مقدار نام‌ها درون ویژگی name Input در کامپوننت UserItemComponent

اگر تمام مراحل را به درستی انجام داده باشید با تصویر زیر روبه‌رو خواهید شد:

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

به شما تبریک می‌گوییم! شما اولین پروژه‌ی خود را با کامپوننت‌ها در انگولار 2 ایجاد کردید. البته این اپلیکیشنی که شما نوشتید بسیار ساده است و طبیعتا باید نرم‌افزارهای پیچیده و کارآمدتری بنویسید. اصلا نگران نباشید. در این سری از دوره‌های آموزشی ما به شما چگونه حرفه‌ای شدن در نوشتن اپلیکیشن‌های انگولار ۲ را می‌آموزیم. در واقع، در این فصل ما یک نرم‌افزار نظرسنجی شبیه Reddit یا Product Hunt را ایجاد خواهیم کرد. این نرم افزار طبیعتا دارای ویژگی‌های بیشتر و کامپوننت‌های حرفه‌ای می‌باشد. اما قبل از شروع ساخت اپلیکیشن جدید، در بخش ۱-۴ نگاهی عمیق‌تر به چگونگی خودراه‌اندازی اپلیکیشن‌های انگولار ۲ خواهیم داشت. و پس از آن نرم‌افزار جدید خود را توسعه می‌دهیم.

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

توجه: دوستان عزیز آموزش ویدیویی انگولار ۵ از مقدماتی تا پیشرفته به زبان فارسی را می‌توانید با کلیک روی اینجا یاد بگیرید. (این دوره در حال برگزاری است)

آموزش حرفه ای انگولار ۵ به زبان فارسی


فصل ۱

فصل ۲

فصل ۳

فصل ۴

فصل ۵

فصل ۶

نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

javadXR
03 اردیبهشت 1396
سلام سایتتون عالی هست فقط بعضی جاها یه خورده اشتباه تایپی داره

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.