การใช้งาน Form กับ การเชื่อมข้อมูลแบบสองทาง ใน Angular เบื้องต้น

เขียนเมื่อ 7 ปีก่อน โดย Ninenik Narkdee
template driven forms ngmodel two way angular

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ template driven forms ngmodel two_way angular

ดูแล้ว 10,724 ครั้ง




เนื้อหานี้จะเป็นการลงรายละเอียดเกี่ยวกับการใช้งานฟอร์ม รวมถึงการเชื่อมข้อมูลแบบสองทาง
หรือที่เรียกว่า Two-way data binding ซึ่งต่อเนื่องจากตอนที่แล้ว
 
เตรียมใช้งาน Template driven forms ใน Angular เบื้องต้น 
 
แต่ก่อนอื่นเราจะทำการปรับไฟล์นิดหน่อย โดยเราจะมีการเรียกใช้ bootstrap css เพื่อให้การ
จัดการรูปแบบการแสดงของฟอร์ม สวยงามขึ้น โดยให้เราเปิดที่ไฟล์ index.html
แล้วเพิ่มโค้ดการเรียกใช้งาน css ไฟล์ดังนี้
 
    <link rel="stylesheet"
          href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">  
 
รูปภาพประกอบ
 


 
 
หลังจากนั้นในไฟล์ staff-form.component.ts เราจะตัดในส่วนของการใช้งาน styleUrls ออก
 
styleUrls:  ['./staff-form.component.css']  
 
เนื่องจากเรามีการเรียกใช้งานจาก bootstrap แล้ว อย่างไรก็ตาม เราสามารถคงส่วนนี้ไว้ เพื่อกำหนด
ค่าเฉพาะ หรือค่าที่กำหนดขึ้นมาเอง เพื่อใช้ร่วมกันได้ แต่ในที่นี้จะขอตัดออกก่อน

 

ไฟล์ staff-form.component.ts

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

@Component({
  moduleId: module.id,
  selector: 'staff-form',
  templateUrl: `./staff-form.component.html`
})
export class StaffFormComponent  { 
  
}
 
 
ก่อนที่เราจะเข้าสู่ขั้นตอนการสร้างฟอร์มสำหรับกรอกข้อมูลเกี่ยวกับ staff ซึ่งเราจะทำเกี่ยวกับ
ข้อมูลสมมติพนักงานของบริษัทแห่งหนึ่ง เราต้องรู้หรือกำหนดแบบ
จำลองของ staff ก่อนว่าจะมีอะไรบ้าง ถึงจะไปวางเลย์เอาท์ฟอร์มได้ 


 

สร้างแบบจำลอง staff class

 
ก็คือการสร้าง class ของข้อมูล staff ให้เราทำการสร้างไฟล์ staff.ts 
เพื่อใช้กำหนดแบบจำลองของ staff class ว่า พนักงานของบริษัท
มีข้อมูลเบื้องต้น อะไรบ้าง 
 
หมายเหตุ: เหตุผลที่เราต้องสร้าง staff class เพื่อเก็บข้อมูลของ staff แทนปกติที่เราสามารถกำหนด
ค่าตัวแปรไว้ใน component ได้เลย ก็เพราะว่า ยิ่ง app มีความซับซ้อนมากขึ้นและมีการเชื่อมโยง
ความสัมพันธ์ระหว่าง Object มากขึ้น ก็จำเป็นที่จะต้องมีการจัดการเกี่ยวกับค่าต่างๆ ให้เหมาะสมตามรูป
แบบการใช้งาน เช่น จากเดิมเราสามารถกำหนดตัวแปร array ของข้อมูลใน compnent เป็น
 
export class StaffFormComponent  { 
  staff = ['John Smoke','Linda Pink','Lisa Mour'];
}
 
ก็เปลี่ยนเป็น
 
export class StaffFormComponent  { 
  staff = [
      new Staff(1,'John Smoke','IT Support'),
      new Staff(2,'Linda Pink','Accounting'),
      new Staff(3,'Lisa Mour','Marketing')
  ];
}
 
จะเห็นว่าการใช้ class ทำให้เราจัดการกับข้อมูลที่ซับซ้อนได้ง่าย
 
ต่อไปมาดูที่ไฟล์ staff.ts ที่เราสร้าง

 

ไฟล์ staff.ts

 

 
 
export class Staff {

  constructor(
    public id: number,
    public name: string,
    public department: string,
    public age?: number
  ) {  }

}

 
จะเห็นว่าเราใช้งานเฉพาะคำสั่ง export class ไม่มีการ import class ใดๆ เข้ามา
และใช้ constructor() ในการกำหนดค่า โดยมีค่าที่ต้องการได้แก่ 
 
id เก็บไอดี กำหนดค่าเป็น number จะคล้ายๆ กับ primary key ในฟิดล์ฐานข้อมูล
name เก็บชื่อ กำหนดค่าเป็น string
department เก็บฝ่ายหรือแผนก กำหนดค่าเป็น string
age เก็บอายุ กำหนดค่าเป็น number สังเกตว่ามีการต่อท้ายด้วย ? นั่นหมายถึงค่านี้เป็น option
จะมีหรือไม่มีก็ได้ การกำหนดค่าเป็น options ต้องไว้ด้านหลังๆของการกำหนด parameter 
 
ตัวอย่างการเรียกใช้งาน
 
 new Staff(3,'Lisa Mour','Marketing') 
 
ตัวสุดท้ายเป็น อายุ แต่เราไม่ได้กำหนดค่าเข้าไปก็ได้ เนื่องจากเรากำหนดให้ age? เป็น option
 
 
เรียกใช้งาน staff class 
โดยให้ทำการ import Staff class ที่สร้างขึ้นมาใช้งานใน StaffFormComponent class ที่ไฟล์
 

ไฟล์ staff-form.component.ts 

 

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

import { Staff } from './staff';

@Component({
  moduleId: module.id,
  selector: 'staff-form',
  templateUrl: `./staff-form.component.html`
})
export class StaffFormComponent  { 
    // กำนหด array เก็บแผนกของ staff
    departments = [
        'Accounting','IT Support','Marketing'
        ];
    // กำหนดตัวแปร model สร้าง staff ใหม่
    model = new Staff(
            6,'John Smoke', this.departments[1],27
        );
    // ตัวอย่างเป็นสร้าง staff ที่มี id = 6 name = 'John Smoke'
    // department = 'IT Support' (ใช้ค่าจากตัวแปร array)        
    // และ age = 27

}
 
 
เราสร้างตัวแปร array เก็บค่าของ departments ซึ่งเป็นจำนวนที่ไม่มาก เราใช้งานเป็นแบบ
array โดยกำหนดเข้ามาใน component ได้
จากนั้นเรากำหนดตัวแปร model เพื่อเรียกใช้งาน staff class สร้าง staff ใหม่ตามค่า
parameter ที่เรากำหนด คำอธิบายเพิ่มเติมแสดงในโค้ดด้านบน
 
 
เมื่อเรารู้แล้วว่า staff มีข้อมูลอะไรบ้าง และเราจะสร้างฟอร์มรับข้อมูล
ให้สัมพันธ์กันอย่างไร ให้เราเปิดไฟล์ staff-form.component.html และกำหนดโค้ดเบื้องต้นดังนี้
 

ไฟล์ staff-form.component.html 

 

 
 
<div class="container">
  <div>
    <h1>Staff Form</h1>
    <form>
      <div class="form-group">
        <label for="name">Name</label>
        <input type="text" class="form-control" id="name" 
            required >
      </div>
      <div class="form-group">
        <label for="age">Age</label>
        <input type="text" class="form-control" id="age">
      </div>
      <div class="form-group">
        <label for="department">Department</label>
        <select class="form-control" id="department"
            required >
          <option></option>
        </select>
      </div>
      <button type="submit" class="btn btn-success">Submit</button>
    </form>
  </div>
 
สังเกตว่าเรามีการใช้งาน css class ของ bootstrap css โดยฟิลด์ที่เราจะรับค่ามาทำการสร้าง staff ใหม่
ได้แก่ name , department และ age 
ใน <input> ที่มีการกำหนด required ลงไปนั้นหมายถึง <input> นั้นจำเป็นต้องมีการส่งค่า ส่วน age
นั้นเราไม่กำหนด required เพราะใน class staff ที่เราสร้าง เราให้ age เป็น option จะมีหรือไม่ก็ได้
จากโค้ด html ข้างต้นเรามีการกำหนด id ของ <input> เพื่อใช้งานกับ tag <label> ใน attribute ที่
ชื่อว่า for แต่ในตอนนี้เรายังไม่ได้กำหนด name attribute ให้กับ <input>
 

ทดสอบรัน app ของเรา จะได้ผลลัพธ์เบื้องต้นดังนี้

 






 
 
 
 

การเชื่อมข้อมูลแบบสองทางหรือแบบไปกลับโดยใช้ ngModel

 
หลังจากที่เราได้วางโครงสร้างของฟอร์ม และสร้าง staff ใหม่โดยใช้ staff class เสร็จแล้ว
เก็บไว้ในตัวแปร model  จากตัวอย่างข้างต้นแล้ว ต่อไป เราจะแสดงให้เห็นถึงการทำงานแบบ
Two-way data binding หรือการเชื่อมข้อมูลแบบไปกลับ ระหว่างข้อมูลในตัวแปร model
และข้อมูลที่แสดงในฟอร์ม โดยเราจะเพิ่มฟังก์ชั่น 
 
get diagnostic() { return JSON.stringify(this.model); }
 
เข้าไปในไฟล์ staff-form.component.ts เพื่อ ตรวจสอบว่าข้อมูลมีการเปลี่ยนแปลง
หรือัพเดทหรือไม่ โดย diagnostic() คือคำสั่งที่เราตั้งขึ้นเพื่อวินิจฉัยส่วนนี้ โดยให้ทำการคืนค่า
ตัวแปร model ที่เป็น Object ออกมาในรูปแบบ string ด้วยคำสั่ง JSON.stringify()
แล้วใช้คำสั่ง get ที่เป็นของ TypeScript แสดงค่าออกมา โดยสามารถเรียกใช้ใน template
หรือไฟล์ html ด้วยการแทรก {{diagnostic}} เพื่อแสดงค่า
 

ไฟล์ staff-form.component.ts

 

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

import { Staff } from './staff';

@Component({
  moduleId: module.id,
  selector: 'staff-form',
  templateUrl: `./staff-form.component.html`
})
export class StaffFormComponent  { 
    // กำนหด array เก็บแผนกของ staff
    departments = [
        'Accounting','IT Support','Marketing'
        ];
    // กำหนดตัวแปร model สร้าง staff ใหม่
    model = new Staff(
            6,'John Smoke', this.departments[1],27
        );
    // ตัวอย่างเป็นสร้าง staff ที่มี id = 6 name = 'John Smoke'
    // department = 'IT Support' (ใช้ค่าจากตัวแปร array)        
    // และ age = 27
    get diagnostic() { return JSON.stringify(this.model); }
}
 

ต่อไปให้เราแก้ไขไฟล์ staff-form.component.html เป็นดังนี้

 

 
 
<div class="container">
  <div>
    <pre>{{diagnostic}}</pre>
    <form>
      <div class="form-group">
        <label for="name">Name</label>
        <input type="text" class="form-control" id="name" 
            required [(ngModel)]="model.name" name="name" >
      </div>
      <div class="form-group">
        <label for="age">Age</label>
        <input type="text" class="form-control" id="age"
            [(ngModel)]="model.age" name="age">
      </div>
      <div class="form-group">
        <label for="department">Department</label>
        <select class="form-control" id="department"
            required [(ngModel)]="model.department" name="department">
          <option *ngFor="let department of departments" 
          [value]="department">{{department}}</option>
        </select>
      </div>
      <button type="submit" class="btn btn-success">Submit</button>
    </form>
  </div>
 
ขออธิบายแยกทีละส่วน เริ่มจากส่วนแรก ที่เราได้ไปทำการสร้างคำสั่งเพิ่มเติมใน StaffFormComponent 
class ที่ชื่อ diagnostic() เพื่อสำหรับตรวจสอบค่าของตัวแปร model ว่าค่าจะเปลี่ยนแปลงเป็นไปตามรูปแบบ
two-way data binding หรือไม่ โดยแสดงใน
 
<pre>{{diagnostic}}</pre>
ด้านบนสุดของฟอร์ม
 
ต่อไปเราจะทำการเชื่อมข้อมูลระหว่างตัวแปร model ให้มาแสดงในฟอร์ม โดยใช้ [(ngModel)]
ยกตัวอย่างในส่วนของ <input> แรก
 
        <label for="name">Name</label>
        <input type="text" class="form-control" id="name" 
            required [(ngModel)]="model.name" name="name" >
 
ในการใช้งาน ngModel เราจะต้องกำหนด name attribute ให้กับ <input> นั้นเสมอ 
จากตัวอย่างเรากำหนด name="name" ค่าของ attribute name ไม่จำเป็นต้องเหมือนกัน
ค่า property ของ model ที่ชื่อ name ใน model.name แต่โดยทั่วไปเพื่อป้องกันการสับสน
ก็สามารถใช้ชื่อเดียวกันได้ ค่าของ <input> เชื่อมกับค่าของ model.name ผ่าน [(ngModel)]
ตามรูปแบบการกำหนด [(ngModel)]="model.name"
 
ทำแบบเดียวกันกับในส่วนของ age และ department
 
ขอยกส่วนของ department มาอธิบายเพิ่มเติม
 
        <label for="department">Department</label>
        <select class="form-control" id="department"
            required [(ngModel)]="model.department" name="department">
          <option *ngFor="let department of departments" 
          [value]="department">{{department}}</option>
        </select>
 
ใน <option> ของ department เราทำการวนลูปนำค่าตัวแปร array ของแผนกของ staff มาแสดง
ใน <select> 
 
คำสั่งนี้เราคุ้นตามาบ้างแล้ว
 
*ngFor="let department of departments" 
 
ส่วนคำสั่ง
 
 [value]="department" 
 
เรียกว่า Property Binding เป็นลักษณะการกำหนดการเชื่อมข้อมูลโดยใช้ attribute 
ใช้ปีกกาสี่เหลี่ยมเปิดปิด ด้านในเป็น attrbute หรือ property รูปแบบ 
 
[target]="expression" 
 
ในที่นี้ target คือ attribute ที่ชื่อ value 
expression คือ ตัวแปร department
 
 
เปรียบเทียบ Property Binding (การเชื่อมข้อมูลด้วย attribute) 
กับ Interpolation (การแทรกค่าตัวแปร)
 
<input [value]="department" >
<input value="{{department}}" >
 
ท้้งสองรูปแบบให้ค่าเหมือนกัน 
 
 

ทดสอบรัน app ของเราดูผลลัพธ์การทำงานแบบการเชื่อมข้อมูลแบบสองทาง

จะได้ผลลัพธ์ดังรูป
 


 
 
เราลองเปลี่ยนค่า จะเห็นว่าของตัวแปร model เปลี่ยนค่าตามไปด้วย นั้นหมายความว่า
ไม่ว่าเราจะเปลี่ยนแปลงค่าในตัวแปร ค่าในฟอร์มที่มีการเชื่อมกันแบบสองทาง ก็จะเปลี่ยน
ค่าไปด้วย เช่นกันกับถ้าเราเปลี่ยนแปลงค่าในฟอร์ม ค่าของตัวแปรก็จะเปลี่ยนไปด้วยเช่นกัน
 


 
 
 
ข้อสังเกต: 
input  element แต่ละตัวจะมีการกำหนด "id" property เพื่อใช้งานร่วมกับ 
"for" attribute ของ label ที่มีค่าตรงกัน
input element จะมี "name" property ที่จำเป็นต้องมีสำหรับ Angualr forms สำหรับใช้งาน
ในการจัดการเกี่ยวกับฟอร์ม เราจะได้ศึกษาในบทความต่อไป


 
 
ก่อนจบเนื้อหาส่วนนี้ ขอเพิ่มเติมในส่วนการเชื่อมข้อมูลในรูปแบบต่างๆ

แยกออกตามทิศทางการเชื่อมข้อมูลได้ 3 รูปแบบคือ

- One-way ใช้ค่าจากตัวแปรข้อมูลไปแสดงผลใน view หรือ template
- One-way ใช้ค่าจากใน view หรือ template ส่งไปยังตัวแปรข้อมูล
- Two-way ใช้ค่าทั้งในตัวแปร และ view ส่งกลับไปมาได้
 

1. One-way ใช้ค่าจากตัวแปรข้อมูลไปแสดงผลใน view หรือ template

 
รูปแบบที่ใช้งาน
 
{{expression}}
[target]="expression"
bind-target="expression"
 
ใช้งานกับ 
 
Interpolation การแทรกค่าตัวแปร เช่น
 
<pre>{{diagnostic}}</pre>
 
Property เช่น 
 
<img bind-src="staffImageUrl">
 
Attribute  เข่น 
 
<option [value]="department"></option>
 
Class เช่น 
 
<div [ngClass]="classes"></div>
<div [class.special]="isSpecial">Special</div>
 
Style เช่น 
 
<button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>
 
 

2. One-way ใช้ค่าจากใน view หรือ template ส่งไปยังตัวแปรข้อมูล

 
รูปแบบที่ใช้งาน
 
(target)="statement"
on-target="statement"
 
ใช้งานกับ 
 
Event เข่น 
 
<button (click)="clickMe()">Click ME!!</button>
<button on-click="onSave()">On Save</button>
 
 

3. Two-way ใช้ค่าทั้งในตัวแปร และ view ส่งกลับไปมาได้

 
รูปแบบที่ใช้งาน
 
[(target)]="expression"
bindon-target="expression"
 
ใช้งานกับ
 
Two-way เช่น
 
<input [(ngModel)]="name">


 


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง





คำแนะนำ และการใช้งาน

สมาชิก กรุณา ล็อกอินเข้าระบบ เพื่อตั้งคำถามใหม่ หรือ ตอบคำถาม สมาชิกใหม่ สมัครสมาชิกได้ที่ สมัครสมาชิก


  • ถาม-ตอบ กรุณา ล็อกอินเข้าระบบ
  • เปลี่ยน


    ( หรือ เข้าใช้งานผ่าน Social Login )







เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ