معرفی رویدادها (Event) و ارتباط آن با Databinding در انگولار

15 آبان 1397
angular-event-binding

همانطور که در فصل گذشته ملاحظه کردید مباحث مربوط به ارتباطات داده‌ای یا databinding را در اختیار شما عزیزان قرار دادیم و نحوه‌ی ارتباط اطلاعات و متغییرها از سمت کنترلر به قالب HTML یا کاربر را بررسی کردیم.

حال طرف دوم ارتباط در two-way databinding به ارسال اطلاعات و پیام‌ها و اعلام نیاز از سمت کاربر یا قالب HTML به سمت کنترلر توسط event binding، مربوط می‌شود. بنابراین در این فصل به صورت کامل این موضوع را پوشش داده و مبحث Databinding را خاتمه می‌دهیم.

Event یا رویداد چیست؟

برای شرح این موضوع یک مثال در دنیای واقعی را برای شما مطرح می‌کنیم.

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

حالت معادل این اتفاق، بدین صورت است که کاربر روی یک دکمه در نرم‌افزار یا اپلیکیشن شما کلیک کرده و در نهایت پاسخی را دریافت می‌کند. بنابراین رویدادها یا event ها به صورت لحظه اتفاق می افتند و منتظر پاسخ می‌مانند.

اما برای روشن تر شدن موضوع شروع به کدنویسی می‌کنیم.

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

بنابراین ابتدا باید یک متغییر با نام serverCreationStatus ایجاد کرده و آن را در صفحه نمایش می‌دهیم. فایل servers.component.ts را به صورت زیر ویرایش می‌کنیم:

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

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

    allowNewServer: boolean = false;

    serverCreationStatus: string = "سروری ایجاد نشده است";

    constructor() {
        setTimeout(() => {
            this.allowNewServer = true;
        }, 2000);
    }

    ngOnInit() {
    }

}

در ادامه برای نمایش این متغییر در قالب HTML فایل servers.components.html را نیز به صورت زیر ویرایش خواهیم کرد:

<button class="btn btn-primary" [disabled]="!allowNewServer">سرور جدید</button>
<p>{{ serverCreationStatus }}</p>
<app-server></app-server>
<app-server></app-server>

در این حالت متن سروری ایجاد نشده است برای شما نمایش داده می‌شود. حال باید یک متد در کلاس کامپوننت ایجاد کرده که به عنوان پاسخ رویداد به کاربر مورد استفاده قرار گیرد. بنابراین فایل servers.component.ts را باز کرده و در نهایت عبارت زیر را به آن می‌افزایم:

import {Component, OnInit} from '@angular/core';
import {createServer} from "http";

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

    allowNewServer: boolean = false;

    serverCreationStatus: string = "سروری ایجاد نشده است";

    constructor() {
        setTimeout(() => {
            this.allowNewServer = true;
        }, 2000);
    }

    ngOnInit() {
    }

    OnCreateServer(){
        this.serverCreationStatus = 'سرور جدید با موفقیت ایجاد شد';
    }
}

به هنگام تعریف متدهایی که به عنوان پاسخ برای یک رویداد یا event مورد استفاده قرار می‌گیرند دقت داشته باشید که همواره کلمه‌ی On در ابتدای آنها باشد. البته این یک اجبار نیست و برای رعایت اصول استاندارد برنامه نویسی در انگولار مطرح شده است.

حال باید فایل مربوط به قالب HTML را ویرایش کنیم. بنابراین برای تگ button یک رویداد به نام click تعریف می‌کنیم.

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

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

<button class="btn btn-primary"
        [disabled]="!allowNewServer"
        (click)="OnCreateServer()">سرور جدید</button>
<p>{{ serverCreationStatus }}</p>
<app-server></app-server>
<app-server></app-server>

همچنین توجه داشته باشید در صورتیکه با خطای زیر مواجه شدید:

Failed to compile.

c:/xampp/htdocs/angular/learning/src/app/servers/servers.component.ts (2,28): Cannot find module 'http'.

باید ماژول http را به فایل app.module به صورت زیر اضافه کنید:

import {BrowserModule} from '@angular/platform-browser';
import {HttpModule} from '@angular/http';
import {NgModule} from '@angular/core';

import {AppComponent} from './app.component';
import {ServerComponent} from "./server/server.component";
import {ServersComponent} from './servers/servers.component';

@NgModule({
    declarations: [
        AppComponent,
        ServerComponent,
        ServersComponent
    ],
    imports: [
        BrowserModule,
        HttpModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule {
}

ارسال و استفاده از داده‌ ها توسط Event در انگولار

تا به اینجای کار نحوه‌ی پیاده‌سازی یک Event و متد موردنظر برای پاسخ به درخواست کاربر را فرا گرفتید.

حال می‌خواهیم با تعریف یک فرم بسیار ساده یک سری اطلاعات را به کنترلر از سمت کاربر و با استفاده از روش Event Binding (طرف دوم ارتباط) ارسال کنیم.

فایل servers.component.html را برای ساخت یک فرم به صورت زیر ویرایش خواهیم کرد:

<label> نام سرور</label>

<input type="text"
       class="form-control"
       (input)="onUpdateServerName($event)"
        >
<p>{{serverName}}</p>

<button class="btn btn-primary"
        [disabled]="!allowNewServer"
        (click)="onCreateServer()">سرور جدید</button>
<p>{{ serverCreationStatus }}</p>
<app-server></app-server>
<app-server></app-server>

اگر توجه داشته باشید مشابه قبل یک event به نام input تعریف کرده و سپس پاسخ به آن را با متد onUpdateServerName ارائه کرده‌ایم. درون متد فوق یک متغییر ورودی به عنوان آرگومان به نام event$ قرار گرفته است. این متغییر حاوی اطلاعاتی‌ست که بر اثر یک رویداد صورت می‌گیرد.

مثلا الان شما یک عبارت را داخل این فرم بنویسید سریعا آن مقدار داخل متغییر event$ ذخیره می‌گردد. در واقع event$ حاوی اطلاعات مفیدی از است که پس از اجرا شدن یک رویداد ذخیره شده و در تمام محیط برنامه در دسترس است.

بنابراین در متد onUpdateServerName می‌خواهیم ورودی‌ای از نوع Event را دریافت کرده و در نهایت مقدار موردنظر تایپ شده را نمایش دهیم.

توجه داشته باشید که عبارت event.target.value به مقدار نهایی شیء event اشاره می‌کند. همچنین یک متغییر به نام serverName تعریف کرده و مقدار پیشفرض آن را خالی گذاشته‌ایم تا با اعمال یک رویداد مقدار جدید را جایگزین آن کرده و در نهایت به خروجی HTML ارسال کنیم.

از طرفی دستور HTMLInputElement برای تبدیل نوع داده‌ی event به داده‌ی دریافتی توسط ورودی می‌باشد (زیرا نوع داده‌ی target یک داده‌ی input می‌باشد). بنابراین در فایل servers.component.ts داریم:

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

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

    allowNewServer: boolean = false;
    serverCreationStatus: string = "سروری ایجاد نشده است";
    serverName: string = '';

    constructor() {
        setTimeout(() => {
            this.allowNewServer = true;
        }, 2000);
    }

    ngOnInit() {
    }

    onCreateServer() {
        this.serverCreationStatus = 'سرور جدید با موفقیت ایجاد شد';
    }

    onUpdateServerName(event: Event) {
        this.serverName = (<HTMLInputElement>event.target).value;
    }
}

حال اگر صفحه مرورگر خود را باز کرده و آدرس http://localhost:4200 را وارد کنید و در نهایت در فرم خود چیزی بنویسید سریعا در صفحه‌ی شما آن نوشته نمایش داده خواهد شد. در صورتیکه خروجی زیر را مشاهده می‌کنید تمام کارها را به درستی انجام داده‌اید:

ارائه مثال برای کار با eventها در انگولار

بنابراین در این آموزش چگونگی کار با شیء رویداد یا event Object را فرا گرفتید و مشاهده کردید که چگونه این اطلاعات انتقال پیدا می‌کند.

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

حال می‌خواهیم در ادامه نحوه‌ی ارسال اطلاعات به صورت دو طرفه یا two-way databinding را به شما عزیزان ارائه دهیم.

معرفی ngModel

می‌توان یک event را از سمت کاربر فعال کرده و سپس نسبت به آن پاسخ داد. حال انگولار یک دستور یا directive تولید کرده که کار انتقال اطلاعات را به صورت دو طرفه تنها با نوشتن یک خط کد فراهم می‌کند.

یعنی نیازی نیست که شما برای دریافت ورودی از کاربر حتما آن را به صورت یک event ذخیره کرده و سپس عملیاتی روی آن انجام دهید. بلکه کافی‌ست دستور زیر را به کدهای خود اضافه کنید. بنابراین ngModel یک حمل کننده اطلاعات می‌باشد که در فرم‌ها استفاده می‌شود.

توجه: برای فراخوانی ngModel همواره باید فایل FormModule را در فایل app.module با استفاده از دستور import بارگذاری کرد.

بنابراین فایل app.module به صورت زیر خواهد بود:

import {BrowserModule} from '@angular/platform-browser';
import {HttpModule} from '@angular/http';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';

import {AppComponent} from './app.component';
import {ServerComponent} from "./server/server.component";
import {ServersComponent} from './servers/servers.component';

@NgModule({
    declarations: [
        AppComponent,
        ServerComponent,
        ServersComponent
    ],
    imports: [
        BrowserModule,
        HttpModule,
        FormsModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule {
}

همچنین برای ویرایش فایل servers.component.html اقدام کرده و در آن یک ویژگی برای ارتباطات داده‌ای به نام ngModel تعریف می‌کنیم. این ویژگی باعث می‌شود هر آنچه درون یک فرم یا ورودی نوشته شود به صورت مستقیم روی متغییر serverName اعمال شود.

از طرفی دیگر، هر تغییری روی serverName از سمت کنترلر اعمال شود، برای کاربر به نمایش گذاشته شود. به این روش ارتباط دو طرفه یا two-way databinding گفته می‌شود.

<label> نام سرور</label>


<input type="text"
       class="form-control"
       [(ngModel)]="serverName"
       >
<p>{{serverName}}</p>

<button class="btn btn-primary"
        [disabled]="!allowNewServer"
        (click)="onCreateServer()">سرور جدید</button>
<p>{{ serverCreationStatus }}</p>
<app-server></app-server>
<app-server></app-server>

در نتیجه خروجی مشابه حالت قبل بوده و هر آنچه درون input‌ وارد کنید در زیر آن نمایش داده خواهد شد.

علاوه بر این می‌توان یک راه حل ایجاد کرد تا با کلیک روی دکمه‌ی «سرور جدید» متن مربوط به آن در پاراگرف‌ها تغییر کرده و نام سرور در کنار آنها نمایش داده شود.

برای اینکار کافی‌ست پارامتر serverName را به متد کلیک onCreateServer به صورت زیر اضافه کنیم، بنابراین تغییرات زیر را به فایل servers.component.ts اعمال خواهیم کرد:

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

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

    allowNewServer: boolean = false;
    serverCreationStatus: string = "سروری ایجاد نشده است";
    serverName: string = 'سرور شماره ۱';

    constructor() {
        setTimeout(() => {
            this.allowNewServer = true;
        }, 2000);
    }

    ngOnInit() {
    }

    onCreateServer() {
        this.serverCreationStatus = 'سرور جدید با موفقیت ایجاد شد و نام این سرور برابر است با: ' + this.serverName;
    }

    onUpdateServerName(event: Event) {
        this.serverName = (<HTMLInputElement>event.target).value;
    }
}

در نهایت خروجی این مثال به صورت زیر خواهد بود:

اعمال امکانات به مثال two-way databinding در انگولار

بسیار عالی به شما عزیزان مجددا تبریک عرض می‌کنیم در این فصل و فصل گذشته با مفاهیم مربوط به Databinding و ارتباطات داده‌ای آشنا شدید و سه روش کلی ارتباط کاربر با کنترلر، ارتباط کنترلر با کاربر و ارتباط دو طرفه را بررسی کردید. در جلسه بعدی مفاهیم مربوط به Databinding در فرم ها را با یکدیگر چک می‌کنیم.

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

دوره آموزش انگولار به زبان فارسی + پروژه ساخت فروشگاه اینترنتی

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش رایگان انگولار توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (3 دیدگاه)

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

رز
11 تیر 1398
سلام مرسی از توضیحات خوبتون من Source انگلیسی اش رو دیدم اصلا متوجه نشدم اما این واقعا عالی بود

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

علی
10 آبان 1396
با سلام غلط: "import {createServer} from "http صحیح : 'import { Http } from '@angular/http لطفا اصلاح بفرمایید

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

پریا
19 مهر 1396
سلام و ممنون از آموزش های خوبتون من اونجا که Error (2,28) میداد کاری که گفتین رو کردم اما بازم همون ارور رو میده متاسفانه.چیکار باید بکنم؟

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

روکسو
22 مهر 1396
با سلام متن خطا را ارسال کنید.

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