วิธีใช้ “ng-model” ใน AngularJS พร้อมตัวอย่าง
⚡ สรุปอย่างชาญฉลาด
ng-model ใน AngularJS ผูกตัวควบคุมอินพุตเข้ากับคุณสมบัติใน $scope โดยตรงping มุมมองและโมเดลจะซิงโครไนซ์กันในทั้งสองทิศทาง หัวข้อด้านล่างจะกล่าวถึงคุณลักษณะ ตัวอย่างการใช้งานสามตัวอย่าง และข้อผิดพลาดที่ผู้เริ่มต้นมักพบเจอ

ng-model ใน AngularJS คืออะไร?
`ng-model` เป็น directive ใน AngularJS ที่ใช้แทนโมเดล โดยมีวัตถุประสงค์หลักคือการเชื่อมโยง "วิว" กับ "โมเดล" สิ่งที่ผู้ใช้พิมพ์ลงในคอนโทรลจะถูกเขียนลงใน property ของ `ng-model` โดยตรง $scopeและสิ่งใดก็ตามที่ตัวควบคุมเขียนลงในคุณสมบัตินั้น จะถูกส่งกลับไปยังตัวควบคุมโดยตรง
ตัวอย่างเช่น สมมติว่าคุณต้องการแสดงหน้าเว็บแบบง่ายๆ ให้ผู้ใช้เห็นดังที่แสดงด้านล่าง ซึ่งขอให้ผู้ใช้ป้อน "ชื่อจริง" และ "นามสกุล" ในช่องข้อความ จากนั้นคุณต้องการตรวจสอบให้แน่ใจว่าได้จัดเก็บข้อมูลที่ผู้ใช้ป้อนลงในแบบจำลองข้อมูลของคุณแล้ว
คุณสามารถใช้คำสั่ง ng-model เพื่อเชื่อมโยงฟิลด์ข้อความ "ชื่อ" และ "นามสกุล" กับโมเดลข้อมูลของคุณได้ คำสั่งนี้จะช่วยให้มั่นใจได้ว่าข้อมูลใน "มุมมอง" และ "โมเดล" ของคุณจะซิงค์กันตลอดเวลา โดยไม่ต้องเขียนโค้ดจัดการเหตุการณ์แม้แต่บรรทัดเดียว
⚠️ หมายเหตุเกี่ยวกับเวอร์ชัน: AngularJS (เวอร์ชัน 1.x) สิ้นสุดการสนับสนุนเมื่อวันที่ 31 ธันวาคม 2021 และจะไม่ได้รับการแก้ไขช่องโหว่ด้านความปลอดภัยอีกต่อไป ตัวอย่างด้านล่างยังคงใช้งานได้ แต่ใน Angular เวอร์ชันใหม่ การผูกข้อมูลแบบสองทางเดียวกันจะเขียนในรูปแบบอื่น [(ngModel)] และต้องใช้ FormsModule
แอตทริบิวต์ ng-model
ดังที่ได้กล่าวไว้ในหัวข้อข้างต้น คุณสมบัติ ng-model ใช้สำหรับเชื่อมโยงข้อมูลในโมเดลของคุณเข้ากับมุมมองที่แสดงต่อผู้ใช้
คุณลักษณะ ng-model ใช้สำหรับ
- การเชื่อมโยงส่วนควบคุมต่างๆ เช่น ช่องป้อนข้อมูล ช่องข้อความ และองค์ประกอบเลือกในมุมมอง เข้ากับโมเดล
- การเพิ่มกลไกการตรวจสอบความถูกต้อง — ตัวอย่างเช่น สามารถเพิ่มการตรวจสอบความถูกต้องให้กับช่องข้อความเพื่อให้สามารถป้อนได้เฉพาะตัวเลขเท่านั้น
- การรักษาสถานะของตัวควบคุม โดยสถานะในที่นี้หมายถึง การที่ตัวควบคุมและข้อมูลจะซิงค์กันอยู่เสมอ: หากค่าของข้อมูลเปลี่ยนแปลง ค่าในตัวควบคุมก็จะเปลี่ยนแปลงโดยอัตโนมัติ และในทางกลับกัน
- แสดงสถานะนั้นออกมาในรูปแบบคลาส CSS AngularJS เพิ่มคุณสมบัตินี้เข้าไป
ng-pristine,ng-dirty,ng-validและng-invalidสำหรับคอนโทรลทุกตัวที่ใช้ ng-model นั้น จะทำให้การกำหนดสไตล์แบบมีเงื่อนไขให้กับฟอร์มทำได้ง่ายขึ้น
เมื่อเข้าใจคุณลักษณะแล้ว ขั้นตอนต่อไปคือการนำไปใช้กับประเภทการควบคุมทั้งสามประเภทที่คุณจะพบเจอบ่อยที่สุด
วิธีการใช้งาน ng-model
1) พื้นที่ข้อความ
แท็กพื้นที่ข้อความใช้เพื่อกำหนดตัวควบคุมการป้อนข้อความแบบหลายบรรทัด พื้นที่ข้อความสามารถเก็บอักขระได้ไม่จำกัดจำนวน และข้อความจะแสดงผลเป็นแบบอักษรที่มีความกว้างคงที่
ต่อไปนี้เรามาดูตัวอย่างง่ายๆ เกี่ยวกับวิธีการเพิ่มคำสั่ง ng-model ลงในตัวควบคุม text area กัน ในตัวอย่างนี้ เราต้องการแสดงวิธีการส่งสตริงหลายบรรทัดจาก controller ไปยัง view และแนบค่าดังกล่าวเข้ากับตัวควบคุม text area
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> <script src="https://code.angularjs.org/1.8.3/angular.js"></script> </head> <body> <h1>Guru99 Global Event</h1> <div ng-app="DemoApp" ng-controller="DemoCtrl"> <form> Topic Description:<br><br> <textarea rows="4" cols="50" ng-model="pDescription"></textarea> </form> </div> <script> var app = angular.module('DemoApp', []); app.controller('DemoCtrl', function($scope) { $scope.pDescription = "This topic looks at how Angular JS works \nModels in Angular JS"; }); </script> </body> </html>
Code คำอธิบาย:
- การขอ คำสั่ง ng-model แนบตัวแปรสมาชิกที่ชื่อว่า “p”Descriptเพิ่ม "ion" ให้กับตัวควบคุม "textarea" "pDescriptตัวแปร “ion” เก็บข้อความที่จะถูกส่งต่อไปยังตัวควบคุมพื้นที่ข้อความ
rows="4"และcols="50"คุณสมบัติเหล่านี้เพียงแค่กำหนดขนาดของตัวควบคุมเพื่อให้ข้อความหลายบรรทัดแสดงผลได้อย่างถูกต้อง - ตัวแปรสมาชิก “p”Descriptไอออน” จะถูกกำหนดค่าเป็นหลายบรรทัด
\nลำดับการหลีกเลี่ยง (escape sequence) ที่อยู่ภายในสตริงจะบังคับให้ข้อความขึ้นบรรทัดใหม่เมื่อ textarea แสดงผล
Output:
จากผลลัพธ์ จะเห็นได้ชัดว่าข้อความหลายบรรทัดที่กำหนดไว้ในตัวควบคุมจะแสดงในพื้นที่ควบคุมข้อความ โดยแบ่งออกเป็นสองบรรทัดตรงจุดที่... \n นั่ง
2) องค์ประกอบอินพุต
คำสั่ง ng-model สามารถใช้งานได้กับองค์ประกอบอินพุตทั่วไปเช่นกัน ด้านล่างนี้ เราได้ผูกกล่องข้อความและช่องทำเครื่องหมายสองช่องพร้อมกัน เพื่อให้คุณเห็นว่า ng-model จัดการค่าสตริงและค่าบูลีนควบคู่กันไปอย่างไร
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> <script src="https://code.angularjs.org/1.8.3/angular.js"></script> </head> <body> <h1>Guru99 Global Event</h1> <div ng-app="DemoApp" ng-controller="DemoCtrl"> <form> Topic Description:<br><br> Name : <input type="text" ng-model="pname"><br> Topic :<br> <input type="checkbox" ng-model="Topic.Controller">Controller<br> <input type="checkbox" ng-model="Topic.Models">Models </form> </div> <script> var app = angular.module('DemoApp', []); app.controller('DemoCtrl', function($scope) { $scope.pname = "Guru99"; $scope.Topic = { Controller: true, Models: false }; }); </script> </body> </html>
Code คำอธิบาย:
- คำสั่ง ng-model จะเชื่อมโยงตัวแปรสมาชิก “pname” กับตัวควบคุมการป้อนข้อความ และคุณสมบัติต่างๆ
Topic.ControllerและTopic.Modelsไปยังตัวควบคุมช่องทำเครื่องหมายทั้งสองช่อง - ในคอนโทรลเลอร์ “pname” จะได้รับสตริง “Guru99” และออบเจ็กต์ “Topic” จะมีสมาชิกแบบบูลีนสองตัว ช่องทำเครื่องหมายที่ผูกกับ ng-model จะอ่านและเขียนค่าบูลีนเสมอ ซึ่งเป็นเหตุผลว่าทำไม
trueแสดงผลช่องดังกล่าวเป็นสถานะถูกเลือก และfalseทำให้ชัดเจน
Output:
จากผลลัพธ์ที่ได้
- จะเห็นได้อย่างชัดเจนว่าค่าที่กำหนดให้กับ
pnameตัวแปรคือ “Guru99. " - เนื่องจากค่าขอบเขตแรกคือ
trueช่องทำเครื่องหมายถูกเลือกสำหรับช่องทำเครื่องหมาย “Controller” ในทำนองเดียวกัน เนื่องจากค่าที่สองคือfalseช่องทำเครื่องหมายสำหรับ "รุ่น" ไม่ได้ถูกทำเครื่องหมายไว้
3) เลือกองค์ประกอบจากดรอปดาวน์
คำสั่ง ng-model สามารถนำไปใช้กับองค์ประกอบ select ได้เช่นกัน เพื่อให้รายการที่ผู้ใช้เลือกถูกจัดเก็บไว้ในโมเดล
ตรงนี้เราจะมีช่องป้อนข้อความซึ่งเก็บชื่อ “Guru99” และรายการเลือกที่มีสองรายการย่อย ได้แก่ “ตัวควบคุม” และ “โมเดล”
⚠️ แก้ไข: ภาพหน้าจอข้างต้นแสดงรายการเดิม ซึ่งผูกองค์ประกอบการเลือกเข้ากับสิ่งเดียวกัน Topics อ็อบเจ็กต์ที่ให้ข้อความตัวเลือก เมื่อผู้ใช้เลือกตัวเลือกใดตัวเลือกหนึ่ง AngularJS จะเขียนทับค่าเดิม Topics เมื่อเลือกสตริงแล้ว ตัวเลือกทั้งสองจะหายไป รายการที่แก้ไขด้านล่างจะเก็บรายการไว้ในคุณสมบัติหนึ่ง และการเลือกไว้ในอีกคุณสมบัติหนึ่ง และใช้ ng-options เพื่อสร้างรายชื่อ
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> <script src="https://code.angularjs.org/1.8.3/angular.js"></script> </head> <body> <h1>Guru99 Global Event</h1> <div ng-app="DemoApp" ng-controller="DemoCtrl"> <form> Topic Description:<br><br> Name : <input type="text" ng-model="pName"><br> Topic :<br> <!-- Topics holds the list; selectedTopic holds the choice --> <select ng-model="selectedTopic" ng-options="t for t in Topics"></select> </form> </div> <script> var app = angular.module('DemoApp', []); app.controller('DemoCtrl', function($scope) { $scope.pName = "Guru99"; $scope.Topics = ["Controller", "Models"]; $scope.selectedTopic = $scope.Topics[0]; }); </script> </body> </html>
Code คำอธิบาย:
- ช่องป้อนข้อความถูกผูกไว้กับ
pNameและองค์ประกอบที่เลือกจะถูกผูกไว้กับselectedTopicเนื่องจากตัวเลือกมีคุณสมบัติโมเดลของตัวเอง การเลือกตัวเลือกจึงไม่รบกวนรายการแต่อย่างใด - การขอ
Topicsอาร์เรย์นี้เก็บค่าสองค่าคือ “Controller” และ “Models”ng-optionsนิพจน์จะวนไปตามอาร์เรย์นั้นและแสดงตัวเลือกหนึ่งรายการต่อหนึ่งหัวข้อ ดังนั้นการเพิ่มหัวข้อที่สามจึงไม่จำเป็นต้องเปลี่ยนแปลงมาร์กอัป selectedTopicค่าเริ่มต้นจะถูกตั้งไว้ที่รายการแรก ซึ่งเป็นสิ่งที่ทำให้เมนูแบบดรอปดาวน์เปิดขึ้นมาพร้อมกับค่าเริ่มต้นที่เหมาะสม แทนที่จะเป็นแถวว่างเปล่า
Output:
จากผลลัพธ์ จะเห็นได้ว่าค่าที่กำหนดให้กับ pName ตัวแปรคือ “Guru99” และตัวควบคุมการเลือกมีตัวเลือก “ตัวควบคุม” และ “โมเดล” นอกเหนือจากตัวอย่างการทำงานแล้ว บางครั้งการผูกข้อมูลอาจไม่ยอมอัปเดต และเหตุผลเหล่านั้นก็คุ้มค่าที่จะทราบ
เหตุใดการผูกข้อมูลด้วย ng-model จึงล้มเหลวในบางครั้ง
ปัญหาที่พบได้บ่อยที่สุดเกี่ยวกับ ng-model ไม่ใช่บั๊กใน AngularJS แต่เป็นผลมาจากวิธีการทำงานของขอบเขต (scopes) และประเภทข้อมูลพื้นฐาน (primitives)
กรณีคลาสสิกคือการผูกค่าไว้ภายในคำสั่งที่สร้างขอบเขตย่อย เช่น ng-ซ้ำng-if หรือ ng-switch การเขียน ng-model="name" วิธีนี้จะสร้างสำเนาเงาในขอบเขตของลูก ทำให้ผู้ปกครองไม่เห็นการแก้ไขนั้น การผูกกับคุณสมบัติของวัตถุแทน — ng-model="user.name" — ช่วยให้ทุกขอบเขตชี้ไปยังการอ้างอิงเดียวกัน นี่คือเหตุผลที่นักพัฒนา AngularJS ที่มีประสบการณ์ยืนยันว่าต้องมีจุดในทุกนิพจน์ ng-model
สาเหตุอีกสองประการที่เหลือเป็นสาเหตุหลักของปัญหาที่เหลือ:
- ตัวควบคุมหรือโมดูลหายไป: หากสะกด ng-app หรือ ng-controller ผิด การเชื่อมต่อจะไม่แสดงผลอะไรเลยแทนที่จะแสดงข้อผิดพลาด
- ค่าที่เปลี่ยนแปลงภายนอก AngularJS: ค่าที่กำหนดจากแฮนด์เลอร์ jQuery หรือฟังก์ชันเรียกกลับ setTimeout จะอยู่นอกรอบการประมวลผล ดังนั้นมุมมองจะไม่รีเฟรชจนกว่าจะถึงเวลานั้น
$scope.$apply()วิ่ง
การตรวจสอบสามสิ่งนี้จะช่วยแก้ปัญหาการเชื่อมต่อส่วนใหญ่ที่ดูเหมือนจะใช้งานไม่ได้







