Angular — Databinding [Part 2]

Panusitt Khuenkham
Angular in Thailand
7 min readSep 22, 2017

> การผูกข้อมูลความสัมพันธ์ต่างๆ

ความเดิมจากตอนที่แล้ววววววว [ตอนที่ 1]

หัวข้อที่เราจะสอนคร่าวๆ ก็จะมีดังนี้

  • Create students component
  • What is Databinding ?
  • String Interpolation
  • Property Binding
  • Property Binding and String Interpolation
  • Event Binding
  • Passing and Using Data with Event Binding
  • Two-Way-Databinding
  • One-Way-Databinding

— — มาลุยกันต่อตอนที่ 2 กันนะค้าบบบบบ เริ่ม……… จับเวลา 55555

Create student component

>> สร้างคอมโพเนนท์

Step 1 : สร้าง Component สำหรับจัดการนักศึกษา

ng g c students --spec false

Step 2 : เปิดไฟล์ app.module.ts ขึ้นมา แล้วกำหนด Router Path

{path: 'student-system', component: StudentsComponent}

Step 3 : เปิดไฟล์ app.component.html ขึ้นมา แล้วสร้างเมนู Student System

<li routerLinkActive="active">
<a [routerLink]="['student-system']">Student System</a>
</li>

ทีนี้เราลองมารันดูผลลัพธ์กัน….

Root project >ng serve

What is Databinding ?

>> Databinding คืออะไร ???

Databinding ถ้าจะให้พูดง่าย ๆ ย้ำนะ!!! ว่าง่ายๆ ก็คือ

  • การผูกข้อมูลฝั่ง Business logic เข้ากับ UI Template หรือ หน้าจอที่ผู้ใช้สามารถเห็นได้ เมื่อข้อมูลมีการเปลี่ยนแปลงค่า มันก็จะไปอัพเดตข้อมูลฝั่ง UI Template ให้เองโดยอัตโนมัติ

เพื่อให้เกิดความเข้าใจมากยิ่งขึ้น เราลองมาดูแผนภาพดังต่อไปนี้

จากรูปอธิบายเพิ่มเติมได้ว่า

ฝั่ง Business logic ส่งค่าข้อมูลไป Output ที่หน้าบ้าน(UI)

ในทางกลับกัน

ฝั่ง หน้าบ้าน(UI) ก็มีปฏิกิริยาตอบโต้กลับมาที่ Business logic

Databinding ก็เปรียบเสมือนการสื่อสารระหว่าง คน 2 คน ที่กำลังพูดคุยกันนั่นเอง

String Interpolation

>> การแก้ไขหรือสอดแทรกข้อความ

Step 4 : ยกตัวอย่างเช่น เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>Student Name: bamossza with ID: 9958</p>

ผลลัพธ์ที่ได้ก็คือ แสดงข้อความตามที่เราได้พิมพ์โค้ดลงไป

อ่าวววว !!! แล้วเกี่ยวไรกับ String Interpolation ว๊าาาา เนี้ย ??

คำตอบก็คือ ไม่เกี่ยวเลย 555555 ^^

แต่!!! ถ้าสมมติว่า ชื่อและหมายเลขไอดี มีการเปลี่ยนแปลงตาม Business logic

จะทำไง “หละ” เรามาดูตัวอย่างด้านนี้

<p>Student Name: bamossza with ID: 9958</p><p>Student Name: ___ with ID: ___</p>

เราจึงจำเปนจะต้องพึ่ง String Interpolation

สัญลักษณ์ >> {{}} >> การใช้งาน >> {{ value or ‘text’ or function }}

Step 5 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

studentId = '9958';
studentName = 'bamossza';

Step 6 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>Student Name: {{ studentName }} with ID: {{ studentId }}</p>

ผลลัพธ์ที่ได้

ช้าก่อนนนนนนนนน String Interpolation ยังใช้กับ function ได้อีกด้วย

Step 7 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

onGetId() {
return this.studentId;
}

onGetName() {
return this.studentName;
}

Step 8 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>Student Name: {{ onGetName() }} with ID: {{ onGetId() }}</p>

ผลลัพธ์ที่ได้

จริงๆ แล้วก็สามารถแสดงค่าได้ทุก Type เลยครับ เช่น array, boolean, etc.

Property Binding

>> การผูกคุณสมบัติ

Step 9 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<button type="button" class="btn btn-primary">Add Student</button>
<hr>

ผลลัพธ์ที่ได้

เรามาลองเล่น คุณสมบัติของปุ่มสักหน่อย เช่น ถ้าต้องการให้ปุ่มนี้ disabled

HTML ปกติเราก็จะเขียนแบบนี้

ผลลัพธ์ที่ได้

เอาหละทีนี้เรามาดูว่า Angular มัน Binding Property ยังไง

Step 10 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

allowNewStudent = false;

Step 11 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<button type="button" class="btn btn-primary"
[disabled]="!allowNewStudent">Add Student</button>
<hr>

ผลลัพธ์ที่ได้

สัญลักษณ์ >> []="" >> การใช้งาน >> [property]="value"

อธิบายเพิ่มเติม : จากตัวอย่างบนก็คือ

[disabled]="!allowNewStudent" >> allowNewStudent = trueเพราะว่าเจอเครื่องหมาย ตกใจ(!) ค่าก็เลยเปลี่ยนเป็น true 

เรามาดูตัวอย่างเพิ่มเติม เพื่อให้เกิดความเข้าใจมากยิ่งขึ้น

โจทย์: เมื่อโปรแกรมรันขึ้นมาให้ปุ่ม Disabled ไว้ก่อน พอเวลาผ่านแล้ว 3 วินาที
ให้ Enabled ปุ่ม

Step 12 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

setTimeout(() => {
this.allowNewStudent = true;
}, 3000);

แล้วเรามาดูผลลัพธ์กัน

พอเวลาผ่านไปแล้วววววว 3 วินาที

เสริมให้อีกนิ๊ดดดดดดดด

// การเขียนแบบ Arrow function
setTimeout(() => {
this.allowNewStudent = true;
}, 3000);
// การเขียนแบบ function ปกติ
setTimeout(function() => {
this.allowNewStudent = true;
}, 3000);

*ตัว Value ยังสามารถประยุกต์ใช้กับ function ที่ return (true/false)ได้อีกนะ

Property Binding and String Interpolation

>> การผูกคุณสมบัติและการแสดงข้อความ

Step 13 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>{{ allowNewStudent }}</p>

ผลลัพธ์ที่ได้

พอเวลาผ่านไปแล้ว 3 วินาที

หรือจะเขียนแบบนี้ก็ได้ ซึ่งก็ได้ผลลัพธ์เหมือนกัน

<p [innerText]="allowNewStudent"></p>

Event binding

>> การผูกอีเว้นท์

Step 14 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

studentCreationStatus = 'No student created!';onCreateStudent() {
this.studentCreationStatus = 'Student created';
}

Step 15 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<button type="button" class="btn btn-primary"
[disabled]="!allowNewStudent"
(click)="onCreateStudent()">Add Student</button>
<p>{{ studentCreationStatus }}</p>

เรามาดูผลลัพธ์ที่ได้

เมื่อยังไม่ได้กดปุ่ม Add Student จะแสดงสถานะ “No student Created!”

เมื่อกดปุ่ม Add Student จะแสดงสถานะ “Student Created”

* โปรดอ่านสักนิ๊ด : ไม่สามารถใช้ onclick ผูกกับ event ได้

ศึกษาคุณสมบัติและอีเว้นท์ของ Element เพิ่มเติมได้ที่

User Input — Binding to user input events

Passing and Using Data with Event Binding

>> การส่งผ่านและการใช้ข้อมูลร่วมกับการอีเว้นท์

Step 16 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

onUpdateStudentName(event: Event) {
console.log(event);
}

Step 17 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>Student Name</p>
<input type="text"
class="form-control"
(input)="onUpdateStudentName($event)">

<button type="button" class="btn btn-primary"
[disabled]="!allowNewStudent"
onClick="onCreateStudent()">Add Student</button>
<p>{{ studentCreationStatus }}</p>
<!--<p [innerText]="allowNewStudent"></p>-->

<p>Student Name: {{ studentName }} with ID: {{ studentId }}</p>

<p>Student Name: {{ onGetName() }} with ID: {{ onGetId() }}</p>

<hr>

ผลลัพธ์ที่ได้

ทีนี้เราลองมากรอกค่าใน Input ดูว่ามี Event อะไรบ้างส่งเข้ามา

ซึ่งก็จะมีข้อมูล Event ส่งมามากมายก่ายกอง ก็แล้วแต่เราจะนำไปใช้

ณ ตอนนี้ ให้เราไป Focus ที่ target object {} เพื่อจะไปเอาค่า Value ของ Input

เปิดมันออกมาาาาาาาาาาาาา แล้วก็หา value ว่าอยู่ไหนน๊าาาาาา

เย้ๆๆๆๆๆๆๆๆๆๆๆๆๆๆ เจอแล้วววววววว ที่นี้เรามากรองเอาแต่ค่า value กัน

Step 18 : เปิดไฟล์ students.component.ts แล้วแก้ไขโค้ดดังนี้

onUpdateStudentName(event: Event) {
const value = (<HTMLInputElement>event.target).value;
console.log(value);
}

มาดูผลลัพธ์กัน

ทีนี้เรามาลองประยุกต์โดยที่ เมื่อกรอก Input แล้ว ให้แสดงค่า Text ด้านล่าง Input

Step 19 : เปิดไฟล์ students.component.ts แล้วเขียนโค้ดดังนี้

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

Step 20 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>{{ studentNewName }}</p>

มาดูผลลัพธ์กัน

เมื่อเรากรอกค่าไปเรื่อยๆ Text มันก็จะแสดงผลตามที่เรากรอก

>_<’’’’ พักเหนื่อย จิบน้ำชา กาแฟ สัก 5 นาที แล้วเรามาลุยในหัวข้อต่อไป

Two-Way-Databinding

>> การผูกข้อมูลสองทาง

ก่อนเริ่มมาเช็ค FormModule ก่อนว่าประกาศหรือยังเพราะจำเป็นต้องใช้

// เปิดไฟล์ app.module.ts ขึ้นมา แล้วเช็คดูว่ามีหรือเปล่า// 1 > เช็ค import
import { FormsModule } from '@angular/forms';
// 2 > เช็คตรงนี้ >> imports: [] ว่าประกาศ FormsModule หรือยัง ?**ตัวอย่าง
imports: [
BrowserModule,
FormsModule
],

Step 20 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

<p>Student Name</p>
<input type="text"
class="form-control"
(input)="onUpdateStudentName($event)">

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

มาดูผลลัพธ์กัน

เมื่อเรากรอกช่องแรก ช่องที่ 2 และ Text ก็จะเปลี่ยนตาม

อธิบายเพิ่มเติม :

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

ลองสังเกตุ Input ตัวนี้ดีๆ

[(ngModel)]="studentNewName"
การเขียนคำสั่งแบบนี้หมายถึงการผูกข้อมูลเข้า 2 ทาง นั่นก็คือ
ถ้า studentNewName มีการเปลี่ยนแปลง ค่าของ Input ก็จะเปลี่ยนตามด้วย
ในทางกลับกัน ถ้า Input ตัวนี้ถูกแก้ไขหรือกรอกค่าใหม่ studentNewName ก็จะถูกเปลี่ยนด้วย

One-Way-Databinding

>> การผูกข้อมูลทางเดียว

Step 21 : เปิดไฟล์ students.component.html แล้วเขียนโค้ดดังนี้

// เดิม
[(ngModel)]="studentNewName"
// แก้ใหม่เป็น
[ngModel]="studentNewName"

มาดูผลลัพธ์กัน

  1. กรอกช่องแรก Test ช่องที่ 2 และ Text จะเปลี่ยนแปลงค่าตามช่องแรก

2. เมื่อกรอกช่องที่ 2 Text จะไม่มีการเปลี่ยนแปลงค่าตามช่อง 2

***เพราะอะไร ???!! ลองสังเกตุ Input ตัวนี้ดีๆ

[ngModel]="studentNewName"
การเขียนคำสั่งแบบนี้หมายถึงการผูกข้อมูลแค่ทางเดียว นั่นก็คือ
ถ้า studentNewName มีการเปลี่ยนแปลง ค่าของ Input ก็จะเปลี่ยนตามด้วย
ในทางกลับกัน ถ้า Input ตัวนี้ถูกแก้ไขหรือกรอกค่าใหม่ studentNewName จะไม่ถูกเปลี่ยนค่า
หรือที่เรียกว่า One-Way-Binding

สรุปแล้ว Two-Way กับ One-Way ต่างกันนิ๊ดเดียวเอง แล้วแต่การนำไปใช้ค้าบ^^

หวังว่าเป็นบทความที่มีความรู้ และสามารถพาท่านเรียนรู้ได้จนเข้าใจ

ตัวอย่างโค้ดโปรเจค ดูได้ที่นี่_CLICK

Reference
https://angular.io
https://cli.angular.io
https://github.com/angular/angular-cli

หากมีข้อผิดพลาดประการใดต้องขออภัยมา ณ ที่นี้ด้วยนะครับ
Thank you so much.

--

--