ngModel ฟอร์แมตและตัวแยกวิเคราะห์


103

ฉันโพสต์คำถามเดียวกันในรูปแบบอื่น แต่ไม่มีใครตอบ ฉันไม่ได้รับภาพที่ชัดเจนว่า Formatters และ Parsers ทำอะไรใน angular js

ตามคำจำกัดความทั้ง Formatters และ Parsers มีลักษณะคล้ายกับฉัน บางทีฉันอาจจะผิดเพราะฉันยังใหม่กับ angularjs นี้

นิยามฟอร์แมต

อาร์เรย์ของฟังก์ชันที่จะดำเนินการเป็นไปป์ไลน์เมื่อใดก็ตามที่ค่าโมเดลเปลี่ยนแปลง แต่ละฟังก์ชันถูกเรียกใช้ในทางกลับกันส่งค่าผ่านไปยังฟังก์ชันถัดไป ใช้เพื่อจัดรูปแบบ / แปลงค่าเพื่อแสดงในการควบคุมและการตรวจสอบความถูกต้อง

นิยามตัววิเคราะห์

อาร์เรย์ของฟังก์ชันที่จะดำเนินการเป็นไปป์ไลน์เมื่อใดก็ตามที่คอนโทรลอ่านค่าจาก DOM แต่ละฟังก์ชันถูกเรียกใช้ในทางกลับกันส่งค่าผ่านไปยังฟังก์ชันถัดไป ใช้ในการฆ่าเชื้อ / แปลงค่าตลอดจนการตรวจสอบความถูกต้อง สำหรับการตรวจสอบความถูกต้องตัววิเคราะห์ควรอัพเดตสถานะความถูกต้องโดยใช้ $ setValidity () และส่งคืนค่าที่ไม่ถูกต้องสำหรับค่าที่ไม่ถูกต้อง

โปรดช่วยให้ฉันเข้าใจคุณลักษณะทั้งสองด้วยตัวอย่างง่ายๆ เราจะชื่นชมตัวอย่างง่าย ๆ ของทั้งสองอย่าง


2
ฟอร์แมตจะแก้ไขค่าที่แสดงของโมเดลเช่นการแสดง(123) 123-1234หมายเลขโทรศัพท์ Parsers อ่านข้อมูลทุกครั้งที่มีการเปลี่ยนแปลงและโดยทั่วไปจะใช้เพื่อตั้งค่าสถานะ $ ที่ถูกต้องของอินพุต เอกสารมีตัวอย่างของทั้งสองอย่าง
km6zla

คำตอบ:


155

หัวข้อนี้ครอบคลุมในคำถามที่เกี่ยวข้องเป็นอย่างดี: จะกรองสองทางใน AngularJS ได้อย่างไร?

สรุป:

  • รูปแบบจะเปลี่ยนวิธีที่ค่าของโมเดลจะปรากฏในมุมมอง
  • พาร์เซอร์เปลี่ยนวิธีบันทึกค่ามุมมองในโมเดล

นี่คือตัวอย่างง่ายๆโดยสร้างจากตัวอย่างในเอกสาร API ของ NgModelController :

  //format text going to user (model to view)
  ngModel.$formatters.push(function(value) {
    return value.toUpperCase();
  });

  //format text from the user (view to model)
  ngModel.$parsers.push(function(value) {
    return value.toLowerCase();
  });

คุณสามารถดูการทำงานได้ที่: http://plnkr.co/UQ5q5FxyBzIeEjRYYVGX?plnkr=legacy

<input type="button" value="set to 'misko'" ng-click="data.name='misko'"/>
<input type="button" value="set to 'MISKO'" ng-click="data.name='MISKO'"/>
<input changecase ng-model="data.name" />

เมื่อคุณพิมพ์ชื่อใน (ดูแบบจำลอง) คุณจะเห็นว่าโมเดลเป็นตัวพิมพ์เล็กเสมอ แต่เมื่อคุณคลิกปุ่มและเปลี่ยนชื่อโดยใช้โปรแกรม (โมเดลที่ต้องการดู) ช่องป้อนข้อมูลจะเป็นตัวพิมพ์ใหญ่เสมอ


2
มีวิธีใดบ้างในการตั้งค่าการเปลี่ยนแปลงนี้เป็นประเภทของผู้ใช้ คุณพูดว่า "ตามโปรแกรม" แต่ฉันกำลังพยายามทำให้ $ viewValue ถูกจัดรูปแบบเมื่อผู้ใช้ป้อนข้อมูลเข้าเช่นสำหรับการจัดรูปแบบหมายเลขบัตรเครดิต
iamyojimbo

3
@SavvasNicholas ถ้าจำไม่ผิดคุณจะใช้ngModel.$setViewValue(transformedInput);ตั้งค่าและngModel.$render();แสดงผลจากฟังก์ชัน $ parsers
Jacob Ensor

ในกรณีของฉันสิ่งที่ทำคือการหวนกลับทันทีโดย$formatters $validators; (
Mikhail Batcer

1
FYI ไม่มีผู้อ้างถึงอีกต่อไป
Chris Brown

1
ฉันสังเกตว่าฟอร์แมตเตอร์ใช้งานได้ก็ต่อเมื่อคุณกดปุ่มไม่ใช่ถ้าคุณพิมพ์ชื่อลงในฟิลด์
เมื่อ

6

การใช้งานอื่นสำหรับฟอร์แมตและตัวแยกวิเคราะห์คือเมื่อคุณต้องการจัดเก็บวันที่ในเวลา UTC และแสดงเป็นเวลาท้องถิ่นบนอินพุตฉันสร้างคำสั่ง datepicker ด้านล่างและตัวกรอง utcToLocal สำหรับสิ่งนี้

(function () {
    'use strict';

    angular
        .module('app')
        .directive('datepicker', Directive);

    function Directive($filter) {
        return {
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                element.addClass('datepicker');
                element.pickadate({ format: 'dd/mm/yyyy', editable: true });

                // convert utc date to local for display
                ngModel.$formatters.push(function (utcDate) {
                    if (!utcDate)
                        return;

                    return $filter('utcToLocal')(utcDate, 'dd/MM/yyyy');
                });

                // convert local date to utc for storage
                ngModel.$parsers.push(function (localDate) {
                    if (!localDate)
                        return;

                    return moment(localDate, 'DD/MM/YYYY').utc().toISOString();
                });
            }
        };
    }
})();

ใช้ตัวกรอง utcToLocal นี้เพื่อให้แน่ใจว่าวันที่ป้อนข้อมูลอยู่ในรูปแบบที่ถูกต้องก่อนที่จะแปลงเป็นเวลาท้องถิ่น

(function () {
    'use strict';

    angular
        .module('app')
        .filter('utcToLocal', Filter);

    function Filter($filter) {
        return function (utcDateString, format) {
            if (!utcDateString) {
                return;
            }

            // append 'Z' to the date string to indicate UTC time if the timezone isn't already specified
            if (utcDateString.indexOf('Z') === -1 && utcDateString.indexOf('+') === -1) {
                utcDateString += 'Z';
            }

            return $filter('date')(utcDateString, format);
        };
    }
})();

moment.jsใช้เพื่อแปลง local เป็นวันที่utc

pickadate.jsเป็นปลั๊กอิน datepicker ที่ใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.