فصل ۹-۱: معرفی فرم‌ها و رویکرد Template-Driven در انگولار ۴

14 آبان 1397
معرفی فرم‌ها و رویکرد Template-Driven در انگولار ۴

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

مقدمه

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

<form>
    <label>نام و نام خانوادگی</label>
    <input type="text" name="name">
    <label>پست الکترونیک</label>
    <input type="text" name="email">
</form>

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

{
    value: {
        name: 'roxo'
        email: 'info@roxo.ir'
    }
    valid: true
}

همانطور که ملاحظه می‌کنید مقادیری که توسط فرم HTML در صفت name دریافت می‌شوند در زبان تایپ اسکریپت یا جاوا اسکریپت به صورت value معادل سازی می‌شوند. همچنین می‌توان برای فرم‌ها اعتبارسنجی ایجاد کرد.

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

۱) رویکرد Template-Driven

در این روش انگولار به المان‌های DOM که در فرم‌های HTML‌ ایجاد می‌شوند اشاره می‌کند و با آنها در تعامل است ولی کدنویسی به صورت HTML‌ انجام شده و انگولار از این کدها استفاده می‌کند.

۲) رویکرد Reactive

در این روش فرم‌ها به صورت برنامه‌ نویسی شده و همزمان (Synchronize) ایجاد می‌شود و از نظر دشواری کمی پیچیده‌تر از حالت اول است.

هر دو روش به صورت کامل به شما توضیح داده خواهد شد.

شروع با یک مثال

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

مثال ابتدایی برای شروع فرم‌ها در انگولار ۴

در این مثال همانطور که ملاحظه می‌کنید یک فرم شامل نام کاربری، ایمیل، سوال امنیتی و پیشنهاد نام‌ کاربری ایجاد کرده‌ایم. حال در این بخش می‌خواهیم به شما عزیزان آموزش دهیم که چگونه انگولار اشیاء جاوا اسکریپت را برای تحلیل و نمایش اطلاعات فرم‌ها مورد استفاده قرار می‌دهد. توجه داشته باشید که در این بخش تمام مباحث به Template-Driven مربوط شده و در فصل ۹-۲ به آموزش رویکرد Reactive می‌پردازیم.

رویکرد Template-Driven

برای شروع کار مثال فوق را در نظر بگیرید. در ابتدا حتما بررسی کنید که در فایل app.module.ts حتما ماژول FormsModule فراخوانی یا Import شده باشد. سپس وارد فایل app.component.html شوید و در ورودی‌های input دستور ngModel و name را اعمال کنید. دستور ngModel به انگولار اطلاع می‌دهد که نوع ورودی این فرم به‌گونه‌ایست که توسط اشیاء جاوا اسکریپت کنترل خواهد شد:

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
            <form (ngSubmit)="onSubmit(f)" #f="ngForm">
                <div id="user-data">
                    <div class="form-group">
                        <label for="username">نام کاربری</label>
                        <input
                                type="text"
                                id="username"
                                class="form-control"
                                ngModel
                                name="username">
                    </div>
                    <button class="btn btn-default" type="button">پیشنهاد نام کاربری</button>
                    <div class="form-group">
                        <label for="email">ایمیل</label>
                        <input
                                type="email"
                                id="email"
                                class="form-control"
                                ngModel
                                name="email">
                    </div>
                </div>
                <div class="form-group">
                    <label for="secret">سوال امنیتی</label>
                    <select
                            id="secret"
                            class="form-control"
                            ngModel
                            name="secret">
                        <option value="pet">نام اولین حیوان خانگی شما؟</option>
                        <option value="teacher">نام اولین معلم شما؟</option>
                    </select>
                </div>
                <button class="btn btn-primary" type="submit">ثبت</button>
            </form>
        </div>
    </div>
</div>

دستور ngModel که یک دستور ساختاری در انگولار است و باعث می‌شود ورودی‌های این فرم کنترل‌پذیر باشند و دستور name که به عنوان یک دستور بنیادی در زبان HTML می‌باشد و برای تعیین نام برای یک ورودی که دارای مقدار است مورد استفاده قرار می‌گیرد.

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

<form (ngSubmit)="onSubmit()">
...
</form>

در واقع با استفاده از این رویداد (event) مشخص می‌کنیم که وقتی روی دکمه‌ی «ثبت» کلیک شد متد onSubmit فعال شود. بنابراین این متد را باید صفحه app.component.ts اضافه کنید:

onSubmit(){
    console.log('Submitted!');
}

حال اگر روی دکمه‌ی «ثبت» در آدرس http://localhost:4200 کلیک کنید عبارت Submitted! در صفحه کنسول شما نمایش داده خواهد شد.

توجه دارید که در حال حاضر در رویکرد Template-Driven هستیم بنابراین تمام کارها در بخش HTML صورت می‌پذیرد. مجددا به فایل app.component.html‌ باز می‌گردیم.

اکنون برای دسترسی به این فرم توسط انگولار باید ابتدا یک Local Reference Template با استفاده از علامت هشتگ و نام دلخواه تعریف کرد (در اینجا نام لوکال رفرنس یا قالب لوکال f# می‌باشد). برای مطالعه‌ی مبحث Local Reference ها مقاله زیر را مطالعه بفرمایید:

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

<form (ngSubmit)="onSubmit(f)" #f="ngForm">
...
</form>

در نهایت برای مشاهده خروجی به هنگام فشردن دکمه‌ی «ثبت» فایل app.component.ts را باز کرده و تغییرات زیر را در متد onSubmit اعمال می‌کنیم:

import {Component} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    suggestUserName() {
        const suggestedName = 'Superuser';
    }

    onSubmit(form: NgForm){
        console.log(form);
    }
}

حال اگر صفحه کنسول را از ابزار توسعه مرورگر خود (با فشردن دکمه‌ی F12 به این ابزار دسترسی پیدا کنید) باز کنید و سپس روی دکمه‌ی «ثبت» کلیک نمایید متوجه خواهید شد که یک شیء جاوا اسکریپت به نام NgForm در اختیار شما قرار می‌گیرد. حال روی عبارت value‌ کلیک و تمام مقادیری که درون فرم خود وارد کرده‌اید را در این قسمت ملاحظه کنید:

username:"roxo"
email:"info@roxo.ir"
secret:"pet"

برای دسترسی به همچین اطلاعات یک روش دیگر وجود دارد و آن استفاده از ViewChild است که در بخش مربوط به کامپوننت‌ها درباره آن توضیحات لازم را ارائه کردیم. برای آشنایی با این ویژگی مقاله زیر را مطالعه بفرمایید:

معرفی مفسر یا دکوراتور ViewChild@

بنابراین برای اعمال این روش فایل app.component.html را باز کرده و مقداری که به عنوان آرگومان به متد onSubmit ارسال شده را حذف می‌کنیم:

<form (ngSubmit)="onSubmit()" #f="ngForm">
...
</form>

سپس در فایل app.component.ts تغییرات زیر را اعمال می‌کنیم:

import {Component, ViewChild} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    @ViewChild('f') signupForm: NgForm;
    suggestUserName() {
        const suggestedName = 'Superuser';
    }

    // onSubmit(form: NgForm){
    //     console.log(form);
    // }

    onSubmit(){
        console.log(this.signupForm)
    }
}

در صورتیکه مجددا صفحه را بارگذاری کنید متوجه می‌شوید که شیء NgForm دقیقا مشابه حالت قبل در دسترس قرار می‌گیرد.

یک سوال: از روش معمولی Local Reference استفاده کنیم یا مفسر ViewChild@؟
پاسخ: روش ViewChild زمانیکه بخواهیم برای فرم خود اعتبارسنجی ایجاد کنیم مورد استفاده قرار می‌گیرد.

اعتبارسنجی فرم‌ها در رویکرد Template-Driven

فرض کنید می‌خواهیم در مثال قبلی محدودیتهایی را برای فیلدها اعمال کنیم به گونه‌ای که هیچ فیلدی خالی نباشد و در فیلد ایمیل اعتبارسنجی برای ساختار ایمیل اعمال شود. در نتیجه برای اعمال این محدودیت‌ها از دو صفت required و email درون فیلدهای ورودی input به صورت زیر استفاده می‌کنیم:

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
            <form (ngSubmit)="onSubmit()" #f="ngForm">
                <div id="user-data">
                    <div class="form-group">
                        <label for="username">نام کاربری</label>
                        <input
                                type="text"
                                id="username"
                                class="form-control"
                                ngModel
                                name="username"
                                required
                                >
                    </div>
                    <button class="btn btn-default" type="button">پیشنهاد نام کاربری</button>
                    <div class="form-group">
                        <label for="email">ایمیل</label>
                        <input
                                type="email"
                                id="email"
                                class="form-control"
                                ngModel
                                name="email"
                                required
                                email>
                    </div>
                </div>
                <div class="form-group">
                    <label for="secret">سوال امنیتی</label>
                    <select
                            id="secret"
                            class="form-control"
                            ngModel
                            name="secret"
                            required>
                        <option value="pet">نام اولین حیوان خانگی شما؟</option>
                        <option value="teacher">نام اولین معلم شما؟</option>
                    </select>
                </div>
                <button class="btn btn-primary" type="submit">ثبت</button>
            </form>
        </div>
    </div>
</div>

بسیار عالی حال اگر فرم خود را باز کنید و بدون وارد کردن چیزی روی دکمه «ثبت» کلیک نمایید در صفحه کنسول شیء NgForm ساخته می‌شود ولی مقدار ویژگی valid برابر false خواهد بود. اکنون می‌خواهیم فرم خود را یک مقداری هوشمندتر کنیم به گونه‌ای که اگر اعتبارسنجی انجام نشده بود دکمه‌ی «ثبت» غیرفعال شود. بنابراین داریم:

<button
    class="btn btn-primary"
    type="submit"
    [disabled]="!f.valid"
    >ثبت
</button>

همانطور که ملاحظه می‌کنید یک ویژگی به نام disabled تعریف کرده و سپس مقدار روبه‌روی آن را متناسب با آنچه در ویژگی valid در شیء f یا NgForm می‌باشد، تعیین می‌کنیم.

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

همچنین می‌توان برای زیباتر شدن فرم درون فایل app.component.css دستورهای زیر را اعمال کرد تا در صورت عدم اعتبارسنجی یک باکس قرمز رنگ اطراف فرم نمایش داده شود، بنابراین داریم:

.container {
    margin-top: 30px;
}

input.ng-invalid.ng-touched {
    border: 1px solid red;
}

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

اعتبارسنجی در انگولار ۴ با رویکرد template-driven

فرض کنید می‌خواهید علاوه بر این یک پیغام خطا در زیر هر فیلد برای کاربر نمایش دهید. برای انجام اینکار ابتدا فایل app.component.html را باز کنید. سپس یک قالب لوکال به نام مثلا email# ایجاد کرده و مقدار روبه‌روی آن را برابر دستور ngModel‌ قرار دهید. این دستور به شما کمک می‌کند تا به کنترلر این فرم دسترسی پیدا کرده و در نهایت متناسب با آن از ویژگی valid برای این formControl استفاده نمایید:

<input
		type="email"
		id="email"
		class="form-control"
		ngModel
		name="email"
		required
		email
		#email="ngModel">
<span class="help-block" *ngIf="!email.valid && email.touched">لطفا آدرس ایمیل را به درستی وارد کنید</span>

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

توجه دارید که اگر بخواهیم از روش ارتباط دو طرفه یا Two-Way Databinding استفاده کنیم باید همواره عبارت ngModel را به صورت زیر درون هر یک از ورودی‌ها قرار دهیم و سپس متناسب با آن یک ویژگی در کلاس کامپوننت موردنظر ایجاد کنیم:

<input type="text" class="form-control" ([ngModel])="something">

// class component

something: string;

گروه‌بندی یک فرم

گاهی نیاز داریم که دسته ورودی را برای اعتبارسنجی انتخاب یا به صورت کلی یک شیء NgForm را به قسمت‌های کوچکتر تبدیل کنیم. در این صورت باید از دستور ngModelGroup درون بزرگترین تگی که شامل ورودی‌ها یا فیلدها است، به صورت زیر استفاده کنیم:

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
            <form (ngSubmit)="onSubmit()" #f="ngForm">
                <div id="user-data" ngModelGroup="userData">
                    <div class="form-group">
                        <label for="username">نام کاربری</label>
                        <input
                                type="text"
                                id="username"
                                class="form-control"
                                ngModel
                                name="username"
                                required
                                >
                    </div>
                    <button class="btn btn-default" type="button">پیشنهاد نام کاربری</button>
                    <div class="form-group">
                        <label for="email">ایمیل</label>
                        <input
                                type="email"
                                id="email"
                                class="form-control"
                                ngModel
                                name="email"
                                required
                                email
                                #email="ngModel">
                        <span class="help-block" *ngIf="!email.valid && email.touched">لطفا آدرس ایمیل را به درستی وارد کنید</span>
                    </div>
                </div>
                <div class="form-group">
                    <label for="secret">سوال امنیتی</label>
                    <select
                            id="secret"
                            class="form-control"
                            ngModel
                            name="secret"
                            required>
                        <option value="pet">نام اولین حیوان خانگی شما؟</option>
                        <option value="teacher">نام اولین معلم شما؟</option>
                    </select>
                </div>
                <button
                        class="btn btn-primary"
                        type="submit"
                        [disabled]="!f.valid"
                        >ثبت
                </button>
            </form>
        </div>
    </div>
</div>

حال اگر آدرس http://localhost:4200 را وارد نمایید، درون صفحه کنسول شیء NgForm‌ نمایش داده می‌شود و در نهایت درون ویژگی value یک ویژگی دیگر به نام userData ایجاد شده است که حاوی اطلاعات ورودی‌هایست که به عنوان زیرمجموعه درون این تگ جایگذاری شده‌اند.

اکنون برای دسترسی به اشیاء جاوااسکریپت موجود در این فرم مشابه قالب لوکال email# باید یک قالب لوکال به نام دلخواه userData# ایجاد کرده و سپس مقدار آن را برابر ngModelGroup قرار دهیم. سپس فرض کنید اعتبارسنجی را روی این گروه انجام دهیم. در این صورت باید یک تگ <p> ایجاد کرده و مشابه آنچه در بخش email بود در این قسمت انجام دهیم. بنابراین تغییرات این تگ‌ها به صورت زیر است:

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
            <form (ngSubmit)="onSubmit()" #f="ngForm">
                <div
                        id="user-data"
                        ngModelGroup="userData"
                        #userData="ngModelGroup"
                    >
                    <div class="form-group">
                        <label for="username">نام کاربری</label>
                        <input
                                type="text"
                                id="username"
                                class="form-control"
                                ngModel
                                name="username"
                                required
                                >
                    </div>
                    <button class="btn btn-default" type="button">پیشنهاد نام کاربری</button>
                    <div class="form-group">
                        <label for="email">ایمیل</label>
                        <input
                                type="email"
                                id="email"
                                class="form-control"
                                ngModel
                                name="email"
                                required
                                email
                                #email="ngModel">
                        <span class="help-block" *ngIf="!email.valid && email.touched">لطفا آدرس ایمیل را به درستی وارد کنید</span>
                    </div>
                </div>
                <p *ngIf="!userData.valid && userData.touched">اطلاعات کاربری شما تکمیل نیست</p>
                <div class="form-group">
                    <label for="secret">سوال امنیتی</label>
                    <select
                            id="secret"
                            class="form-control"
                            ngModel
                            name="secret"
                            required>
                        <option value="pet">نام اولین حیوان خانگی شما؟</option>
                        <option value="teacher">نام اولین معلم شما؟</option>
                    </select>
                </div>
                <button
                        class="btn btn-primary"
                        type="submit"
                        [disabled]="!f.valid"
                        >ثبت
                </button>
            </form>
        </div>
    </div>
</div>

در ادامه می‌خواهیم مثال فوق را گسترش داده و به آن دکمه‌های رادیویی یا Radio Button اضافه کنیم. فرض کنید می‌خواهیم دو دکمه‌ی رادیویی برای مشخص کردن جنسیت کاربر درنظر بگیریم. در این حالت ابتدا وارد فایل app.component.ts شده و سپس یک متغییر به نام genders با دو مقدار "مرد" و "زن" تعریف کنیم:

import {Component, ViewChild} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    @ViewChild('f') signupForm: NgForm;

    genders = ['مرد', 'زن']

    suggestUserName() {
        const suggestedName = 'Superuser';
    }

    // onSubmit(form: NgForm){
    //     console.log(form);
    // }

    onSubmit(){
        console.log(this.signupForm)
    }
}

سپس درون فایل app.component.html با استفاده از یک حلقه‌ی for این دکمه‌های رادیویی را نمایش داده و اعتبارسنجی آن را به صورت required انجام می‌دهیم:

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
            <form (ngSubmit)="onSubmit()" #f="ngForm">
                <div
                        id="user-data"
                        ngModelGroup="userData"
                        #userData="ngModelGroup"
                    >
                    <div class="form-group">
                        <label for="username">نام کاربری</label>
                        <input
                                type="text"
                                id="username"
                                class="form-control"
                                ngModel
                                name="username"
                                required
                                >
                    </div>
                    <button class="btn btn-default" type="button">پیشنهاد نام کاربری</button>
                    <div class="form-group">
                        <label for="email">ایمیل</label>
                        <input
                                type="email"
                                id="email"
                                class="form-control"
                                ngModel
                                name="email"
                                required
                                email
                                #email="ngModel">
                        <span class="help-block" *ngIf="!email.valid && email.touched">لطفا آدرس ایمیل را به درستی وارد کنید</span>
                    </div>
                </div>
                <p *ngIf="!userData.valid && userData.touched">اطلاعات کاربری شما تکمیل نیست</p>
                <div class="form-group">
                    <label for="secret">سوال امنیتی</label>
                    <select
                            id="secret"
                            class="form-control"
                            ngModel
                            name="secret"
                            required>
                        <option value="pet">نام اولین حیوان خانگی شما؟</option>
                        <option value="teacher">نام اولین معلم شما؟</option>
                    </select>
                </div>
                <div class="radio" *ngFor="let gender of genders">
                    <label>
                        <input
                            type="radio"
                            name="gender"
                            [value]="gender"
                            ngModel
                            required
                        >
                        {{ gender }}
                    </label>
                </div>
                <button
                        class="btn btn-primary"
                        type="submit"
                        [disabled]="!f.valid"
                        >ثبت
                </button>
            </form>
        </div>
    </div>
</div>

به‌کارگیری دکمه‌ی «پیشنهاد نام کاربری»

همانطور که در فرم خود مشاهده می‌کنید از ابتدا تا کنون دکمه‌ای تحت عنوان «پیشنهاد نام کاربری» در صفحه قرار گرفته است که از آن استفاده نشده است. در این بخش می‌خواهیم آموزش دهیم که وقتی کاربر روی این دکمه کلیک کرد یک نام کاربری پیشنهادی در فیلد نام کاربری ایجاد شود. برای اینکار ابتدا فایل app.component.ts را باز کرده و سپس با دسترسی به userData و سایر المان‌ها از طریق ViewChild این تغییرات را لحاظ می‌کنیم:

import {Component, ViewChild} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    @ViewChild('f') signupForm: NgForm;

    genders = ['مرد', 'زن']


    suggestUserName() {
        const suggestedName = 'Superuser';
        this.signupForm.setValue({
            userData:{
                username: suggestedName,
                email: ''
            },
            secret: '',
            gender: 'مرد'
        })
    }

    // onSubmit(form: NgForm){
    //     console.log(form);
    // }

    onSubmit(){
        console.log(this.signupForm)
    }
}

در نهایت درون فایل app.component.html باید این رویداد را به هنگام کلیک کردن ثبت کنیم. بنابراین در دکمه‌ی «پیشنهاد نام کاربری» داریم:

<button class="btn btn-default" type="button" (click)="suggestUserName()">پیشنهاد نام کاربری</button>

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

this.signupForm.form.patchValue({
	userData:{
		username: suggestedName
	}
})

نمایش داده

فرض کنید می‌خواهیم وقتی کاربر روی دکمه‌ی «ثبت» کلیک کرد اطلاعات در انتهای صفحه نمایش داده شود. بنابراین ابتدا درون فایل app.component.ts تغییرات زیر را لحاظ می‌کنیم:

import {Component, ViewChild} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    @ViewChild('f') signupForm: NgForm;

    genders = ['مرد', 'زن']
    user ={
        username: '',
        email: '',
        secret: '',
        gender: ''
    }
    submitted= false;

    suggestUserName() {
        const suggestedName = 'Superuser';
        // this.signupForm.setValue({
        //     userData:{
        //         username: suggestedName,
        //         email: ''
        //     },
        //     secret: '',
        //     gender: 'مرد'
        // })
        this.signupForm.form.patchValue({
            userData:{
                username: suggestedName
            }
        })
    }

    // onSubmit(form: NgForm){
    //     console.log(form);
    // }

    onSubmit(){
        this.submitted = true;
        this.user.username = this.signupForm.value.userData.username;
        this.user.email = this.signupForm.value.userData.email;
        this.user.secret = this.signupForm.value.secret;
        this.user.gender = this.signupForm.value.gender;
    }
}

در نهایت در فایل خروجی app.component.html باید یک شرط قرار دهیم که در صورتیکه روی دکمه‌ی «ثبت» کلیک شد آنگاه اطلاعات نمایش داده شود بنابراین داریم:

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
            <form (ngSubmit)="onSubmit()" #f="ngForm">
                <div
                        id="user-data"
                        ngModelGroup="userData"
                        #userData="ngModelGroup"
                    >
                    <div class="form-group">
                        <label for="username">نام کاربری</label>
                        <input
                                type="text"
                                id="username"
                                class="form-control"
                                ngModel
                                name="username"
                                required
                                >
                    </div>
                    <button class="btn btn-default" type="button" (click)="suggestUserName()">پیشنهاد نام کاربری</button>
                    <div class="form-group">
                        <label for="email">ایمیل</label>
                        <input
                                type="email"
                                id="email"
                                class="form-control"
                                ngModel
                                name="email"
                                required
                                email
                                #email="ngModel">
                        <span class="help-block" *ngIf="!email.valid && email.touched">لطفا آدرس ایمیل را به درستی وارد کنید</span>
                    </div>
                </div>
                <p *ngIf="!userData.valid && userData.touched">اطلاعات کاربری شما تکمیل نیست</p>
                <div class="form-group">
                    <label for="secret">سوال امنیتی</label>
                    <select
                            id="secret"
                            class="form-control"
                            ngModel
                            name="secret"
                            required>
                        <option value="pet">نام اولین حیوان خانگی شما؟</option>
                        <option value="teacher">نام اولین معلم شما؟</option>
                    </select>
                </div>
                <div class="radio" *ngFor="let gender of genders">
                    <label>
                        <input
                            type="radio"
                            name="gender"
                            [value]="gender"
                            ngModel
                            required
                        >
                        {{ gender }}
                    </label>
                </div>
                <button
                        class="btn btn-primary"
                        type="submit"
                        [disabled]="!f.valid"
                        >ثبت
                </button>
            </form>
        </div>
    </div>
    <div class="row" *ngIf="submitted">
        <div class="col-xs-12">
            <h3>اطلاعات شما</h3>
            <p>نام کاربری: {{ user.username}}</p>
            <p>ایمیل: {{ user.email}}</p>
            <p>سوال امنیتی: {{ user.secret}}</p>
            <p>جنسیت: {{ user.gender}}</p>
        </div>
    </div>
</div>

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

نمایش اطلاعات در فرم‌های انگولار ۴

بازنویسی فرم

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

import {Component, ViewChild} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    @ViewChild('f') signupForm: NgForm;

    genders = ['مرد', 'زن']
    user ={
        username: '',
        email: '',
        secret: '',
        gender: ''
    }
    submitted= false;

    suggestUserName() {
        const suggestedName = 'Superuser';
        // this.signupForm.setValue({
        //     userData:{
        //         username: suggestedName,
        //         email: ''
        //     },
        //     secret: '',
        //     gender: 'مرد'
        // })
        this.signupForm.form.patchValue({
            userData:{
                username: suggestedName
            }
        })
    }

    // onSubmit(form: NgForm){
    //     console.log(form);
    // }

    onSubmit(){
        this.submitted = true;
        this.user.username = this.signupForm.value.userData.username;
        this.user.email = this.signupForm.value.userData.email;
        this.user.secret = this.signupForm.value.secret;
        this.user.gender = this.signupForm.value.gender;
        
        this.signupForm.reset();
    }
}

بسیار عالی به شما عزیزان تبریک می‌گوییم. در این فصل توانستید با ngForm در انگولار ۴ کار کنید و فرم‌های پیشرفته‌ای را به سادگی هرچه تمام تر تولید کنید. در فصل بعدی به صورت پیشرفته‌تر و با استفاده از رویکرد reactive فرم‌ها را تولید خواهید کرد. با ما همراه باشید.

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

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


فصل ۱

فصل ۲

فصل ۳:‌ خطایابی (Debugging) در انگولار ۴

فصل ۴

فصل ۵

فصل ۶

فصل ۷

فصل ۸: معرفی Observable یا مشاهده کننده‌ها در انگولار ۴

فصل ۹

فصل ۱۰: معرفی فیلترها یا Pipes در انگولار ۴

فصل ۱۱: معرفی درخواست‌های Http در انگولار ۴

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

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

علیرضا
21 شهریور 1397
عالی ممنون

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