จะจัดรูปแบบวันที่โดยใช้ ng-model ได้อย่างไร?


94

ฉันมีอินพุตที่กำหนดเป็น

<input class="datepicker" type="text" ng-model="clientForm.birthDate" />

ซึ่งถูกกำหนดให้แสดงที่อื่นในหน้า:

<tr>
    <th>Birth Date</th>
    <td>{{client.birthDate|date:'mediumDate'}}</td>
</tr>

Dec 22, 2009เมื่อโหลดหน้าเว็บวันเดือนปีเกิดมีรูปแบบเดียวกับสิ่งที่ชอบ อย่างไรก็ตามเมื่อฉันมองเข้าไปข้างใน<input>มันจะปรากฏขึ้นตามTue Dec 22 2009 00:00:00 GMT-0800 (Pacific Standard Time)ที่ฉันเดาว่า JS แสดงผลDateวัตถุเป็นสตริงอย่างไร

ประการแรกฉันจะบอกให้ Angular แสดงวันที่ในรูปแบบ<input>เป็น12/22/2009อย่างไร ดูเหมือนจะใช้|filtersในng-modelแอตทริบิวต์ไม่ได้

ประการที่สองทันทีที่ฉันแก้ไขวันที่แม้จะเก็บไว้ในรูปแบบดั้งเดิมข้อความอื่น ๆ ของฉัน (ภายใน<td>) ดูเหมือนจะไม่ใช้|dateตัวกรองอีกต่อไป จู่ๆก็เปลี่ยนรูปแบบเพื่อให้ตรงกับช่องข้อความที่ป้อน ฉันจะใช้|dateฟิลเตอร์ทุกครั้งที่มีการเปลี่ยนแปลงโมเดลได้อย่างไร


คำถามที่เกี่ยวข้อง:


ฉันมีปัญหาด้วยเช่นกัน แต่มาพร้อมกับวิธีแก้ปัญหาที่ง่ายกว่าโดยใช้Date()ฟังก์ชันjs มาตรฐาน: $scope.departDate = new Date(); $scope.departTime = $scope.departDate.toTimeString().slice(0, 5);และไม่จำเป็นต้องใช้ตัวกรองอื่น ๆ หรือวิธีแก้ปัญหาที่ยุ่งยากใน AngularJS IMO
boldnik

คำตอบ:


71

ใช้การตรวจสอบความถูกต้องของแบบฟอร์มที่กำหนดเองhttp://docs.angularjs.org/guide/forms Demo: http://plnkr.co/edit/NzeauIDVHlgeb6qF75hX?p=preview

คำสั่งโดยใช้ตัวจัดรูปแบบและตัวแยกวิเคราะห์และMomentJS )

angModule.directive('moDateInput', function ($window) {
    return {
        require:'^ngModel',
        restrict:'A',
        link:function (scope, elm, attrs, ctrl) {
            var moment = $window.moment;
            var dateFormat = attrs.moDateInput;
            attrs.$observe('moDateInput', function (newValue) {
                if (dateFormat == newValue || !ctrl.$modelValue) return;
                dateFormat = newValue;
                ctrl.$modelValue = new Date(ctrl.$setViewValue);
            });

            ctrl.$formatters.unshift(function (modelValue) {
                if (!dateFormat || !modelValue) return "";
                var retVal = moment(modelValue).format(dateFormat);
                return retVal;
            });

            ctrl.$parsers.unshift(function (viewValue) {
                var date = moment(viewValue, dateFormat);
                return (date && date.isValid() && date.year() > 1950 ) ? date.toDate() : "";
            });
        }
    };
});

4
ฉันต้องการสร้างตัวอย่างเล็ก ๆ ของ formater และ parser ขอบคุณสำหรับคำถามของคุณในวันนี้ฉันมีเหตุผลที่จะทำ
SunnyShah

1
@ มาร์คแก้ไขปัญหาน่านในซอสอง ;)
SunnyShah

1
ลบแนวทางที่สอง มันเป็นทางที่ผิดเกินไป
SunnyShah

1
คุณสามารถใช้คำสั่งเกี่ยวกับการเปลี่ยนแปลงเพื่อทำการปรับปรุงเพิ่มเติม stackoverflow.com/questions/14477904/…
SunnyShah

7
@SunnyShah - สิ่งที่ดีมีประโยชน์จริงๆขอบคุณมาก ฉันสงสัยว่าทำไมคุณถึงมีvar dateFormat = attrs.moMediumDate;และไม่var dateFormat = attrs.moDateInput;moMediumDate ดูเหมือนจะไม่ถูกตั้งค่าไว้ที่ใดก็ได้ดังนั้นหากไม่ได้สร้างอินพุตแบบไดนามิกจะไม่เลือกรูปแบบเริ่มต้น
toxaq

37

นี่คือคำสั่งที่มีประโยชน์มากเชิงมุม-datetime คุณสามารถใช้งานได้ดังนี้:

<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate">

นอกจากนี้ยังเพิ่มหน้ากากให้กับข้อมูลที่คุณป้อนและทำการตรวจสอบ


1
ฉันใช้คำสั่งนี้เช่นกันขอบคุณ หากคุณใช้กับ jQuery UI Datepicker คุณต้องตรวจสอบให้แน่ใจว่ารูปแบบที่ระบุในdatetime="<format>"ค่าแอตทริบิวต์ตรงกับรูปแบบที่ระบุในdateFormatตัวเลือกDatepicker
tylerwal

1
ฉันสงสัยว่าเป็นไปได้อย่างไรที่จะมีโซลูชันที่สมบูรณ์แบบที่นี่โดยมีคะแนนเสียงเพียงไม่กี่คะแนน มากสำหรับวันที่และคุณสามารถแก้ปัญหาได้ที่นี่ตอนนี้! ขอบคุณครับ.
C0ZEN

2
ฉันแน่ใจว่าจะมีคนโหวตเรื่องนี้มากขึ้นหากเอกสารได้รับการปรับปรุงเพื่อให้ง่ายต่อการรวมไว้ในแอปเชิงมุมที่มีอยู่
Joel Hansen

8

ฉันได้สร้างคำสั่งง่ายๆเพื่อให้input[type="date"]องค์ประกอบฟอร์มมาตรฐานทำงานได้อย่างถูกต้องกับ AngularJS ~ 1.2.16

ดูที่นี่: https://github.com/betsol/angular-input-date

และนี่คือการสาธิต: http://jsfiddle.net/F2LcY/1/


เฮ้ @Lorenzo คุณหมายถึงอะไร? คุณช่วยอธิบายให้ละเอียดได้ไหม
Slava Fomin II

วันเดือนปีเป็นภาษาฝรั่งเศสเช่น Lun Mar Mer สำหรับ Mon Tue, Wen
Merlin

@Lorenzo ฉันไม่แน่ใจว่าฉันไม่เข้าใจ คำสั่งไม่มีส่วนเกี่ยวข้องกับการแปลเป็นภาษาท้องถิ่น อาจเป็นไปได้ว่าฟังก์ชันการจัดรูปแบบที่คุณใช้กำลังรับการตั้งค่าภาษาจากเบราว์เซอร์ / ระบบของคุณ หากคุณให้ตัวอย่างฉันจะสามารถช่วยได้ (jsfiddle)
Slava Fomin II

1
แค่รองรับ chrome แย่มาก
GeminiYellow

เป้าหมายของคำสั่งคือการสนับสนุนทุกแพลตฟอร์ม หากคุณมีปัญหาทำไมคุณไม่สร้างปัญหาใน GitHub repo? ฉันตอบทุกประเด็นเสมอ
Slava Fomin II

7

ฉันใช้ jquery datepicker เพื่อเลือกวันที่ วันที่อ่านคำสั่งของฉันและแปลงเป็นรูปแบบวันที่ json (เป็นมิลลิวินาที) เก็บในng-modelข้อมูลในขณะที่แสดงวันที่ที่จัดรูปแบบและย้อนกลับหาก ng-model มีวันที่ json (เป็นมิลลิวินาที) ฟอร์แมตเตอร์ของฉันแสดงในรูปแบบของฉันเป็น jquery datepicker

รหัส Html:

<input type="text" jqdatepicker  ng-model="course.launchDate" required readonly />

คำสั่งเชิงมุม:

myModule.directive('jqdatepicker', function ($filter) {
    return {
        restrict: 'A',
        require: 'ngModel',
         link: function (scope, element, attrs, ngModelCtrl) {
            element.datepicker({
                dateFormat: 'dd/mm/yy',
                onSelect: function (date) {   
                    var ar=date.split("/");
                    date=new Date(ar[2]+"-"+ar[1]+"-"+ar[0]);
                    ngModelCtrl.$setViewValue(date.getTime());            
                    scope.$apply();
                }
            });
            ngModelCtrl.$formatters.unshift(function(v) {
            return $filter('date')(v,'dd/MM/yyyy'); 
            });

        }
    };
});

โอวพระเจ้า!! ขอบคุณมาก !! ฉันหาคำตอบแบบนี้มาสองวันแล้ว แต่หาไม่เจอ! คุณร็อค!
Michael Rentmeister

ยอดเยี่ยม. ฉันหาอะไรแบบนี้มาสักพักแล้ว ฉันใช้ materializecss สำหรับการแก้ปัญหาของฉัน หากมีคนสะดุดกับสิ่งนี้และต้องการแปลงคำสั่งนี้เพื่อให้เป็นจริงเพียงแค่สลับelement.datepickerกับelement.pickadate
IWI

7

เนื่องจากคุณใช้ datepicker เป็นชั้นเรียนฉันจึงสมมติว่าคุณใช้ Jquery datepicker หรือสิ่งที่คล้ายกัน

มีวิธีทำในสิ่งที่คุณตั้งใจโดยไม่ต้องใช้ moment.js เลยโดยใช้คำสั่ง datepicker และ angularjs เท่านั้น

ฉันได้ยกตัวอย่างไว้ที่นี่ในFiddleนี้

ข้อความที่ตัดตอนมาจากซอที่นี่:

  1. Datepicker มีรูปแบบที่แตกต่างกันและรูปแบบ angularjs แตกต่างกันจำเป็นต้องค้นหาการจับคู่ที่เหมาะสมเพื่อให้วันที่ถูกเลือกไว้ล่วงหน้าในการควบคุมและจะเติมข้อมูลในช่องป้อนข้อมูลในขณะที่ ng-model ถูกผูกไว้ รูปแบบด้านล่างนี้เทียบเท่ากับ'mediumDate'รูปแบบของ AngularJS

    $(element).find(".datepicker")
              .datepicker({
                 dateFormat: 'M d, yy'
              }); 
    
  2. คำสั่งการป้อนวันที่จำเป็นต้องมีตัวแปรสตริงชั่วคราวเพื่อแสดงถึงรูปแบบวันที่ที่มนุษย์อ่านได้

  3. สดชื่นทั่วส่วนที่แตกต่างกันของหน้าควรจะเกิดขึ้นผ่านเหตุการณ์เช่นและ$broadcast$on

  4. การใช้ตัวกรองเพื่อแสดงวันที่ในรูปแบบที่มนุษย์อ่านได้เป็นไปได้ใน ng-model เช่นกัน แต่มีตัวแปรโมเดลชั่วคราว

    $scope.dateValString = $filter('date')($scope.dateVal, 'mediumDate');
    

6

ฉันใช้คำสั่งต่อไปนี้ที่ทำให้ฉันและผู้ใช้ส่วนใหญ่มีความสุขมาก! ใช้ช่วงเวลาในการแยกวิเคราะห์และจัดรูปแบบ ดูเหมือนว่าซันนี่ชาห์กล่าวไว้ก่อนหน้านี้เล็กน้อย

angular.module('app.directives')

.directive('appDatetime', function ($window) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var moment = $window.moment;

            ngModel.$formatters.push(formatter);
            ngModel.$parsers.push(parser);

            element.on('change', function (e) {
                var element = e.target;
                element.value = formatter(ngModel.$modelValue);
            });

            function parser(value) {
                var m = moment(value);
                var valid = m.isValid();
                ngModel.$setValidity('datetime', valid);
                if (valid) return m.valueOf();
                else return value;
            }

            function formatter(value) {
                var m = moment(value);
                var valid = m.isValid();
                if (valid) return m.format("LLLL");
                else return value;

            }

        } //link
    };

}); //appDatetime

ในรูปแบบของฉันฉันใช้แบบนี้:

<label>begin: <input type="text" ng-model="doc.begin" app-datetime required /></label>
<label>end: <input type="text" ng-model="doc.end" app-datetime required /></label>

นี้จะผูกประทับเวลา (มิลลิวินาทีตั้งแต่ปี 1970) ไปและdoc.begindoc.end


1
มันเป็นเรื่องง่ายที่จะมองข้ามความจริงที่ว่าภายในฟังก์ชั่นการเชื่อมโยงนี้เป็นตัวบ่งชี้ที่กำหนดเองของคุณสำหรับอาร์กิวเมนต์ควบคุมไม่ตรงชื่ออ้างอิงถึงngModel ngModelนี่คือจุดที่หลักการตั้งชื่อนั้น arg 'ctrl' หรือ 'controller' ช่วยให้สิ่งต่างๆชัดเจนขึ้นและหลีกเลี่ยงความสับสน
XML

ขอบคุณ! ฉันมองหาวิธีที่ดีในการทำสิ่งนี้มาตลอดทั้งวัน น่าเสียดายที่การแก้ไขอื่น ๆ ส่วนใหญ่เกี่ยวข้องกับการเปลี่ยนไปใช้ datepicker ที่เขียนขึ้นโดยเฉพาะสำหรับเชิงมุมและนั่นก็ใช้งานได้มากเกินไป
Josh Mouch

ฉันลองทั้งของคุณและคำตอบของ @SunnyShah แต่ดูเหมือนว่าเขาจะไม่ได้ผล ไม่แน่ใจว่าทำไม
Josh Mouch

3

ใน Angular2 + สำหรับทุกคนที่สนใจ:

<input type="text" placeholder="My Date" [ngModel]="myDate | date: 'longDate'">

ด้วยประเภทของตัวกรองในDatePipe Angular


แดงฉันติดอยู่ใน AngularJS มรดกซึ่งฉันถูกบังคับให้ทำงานและฉันเกลียดมัน! หวังว่าฉันจะมีข้อมูลข้างต้นในการทำงานด้วย
จอร์แดน

นี่เป็นเพียงการแกล้งผู้คนและหลอกให้พวกเขาใช้ Angular2 + อึ๊บ! AngularJs เป็นระเบิด ทำไมใคร ๆ ก็ต้องการวิธีง่ายๆเช่นนี้
Nebulosar

2

ฉันต้องการให้เซิร์ฟเวอร์ส่งคืนวันที่โดยไม่ต้องแก้ไขและให้ javascript ทำการนวดดู API ของฉันส่งคืน "MM / DD / YYYY hh: mm: ss" จาก SQL Server

ทรัพยากร

angular.module('myApp').factory('myResource',
    function($resource) {
        return $resource('api/myRestEndpoint/', null,
        {
            'GET': { method: 'GET' },
            'QUERY': { method: 'GET', isArray: true },
            'POST': { method: 'POST' },
            'PUT': { method: 'PUT' },
            'DELETE': { method: 'DELETE' }
        });
    }
);

ตัวควบคุม

var getHttpJson = function () {
    return myResource.GET().$promise.then(
        function (response) {

            if (response.myDateExample) {
                response.myDateExample = $filter('date')(new Date(response.myDateExample), 'M/d/yyyy');
            };

            $scope.myModel= response;
        },
        function (response) {
            console.log(response.data);
        }
    );
};

คำสั่งการตรวจสอบ myDate

angular.module('myApp').directive('myDate',
    function($window) {
        return {
            require: 'ngModel',
            link: function(scope, element, attrs, ngModel) {

                var moment = $window.moment;

                var acceptableFormats = ['M/D/YYYY', 'M-D-YYYY'];

                function isDate(value) {

                    var m = moment(value, acceptableFormats, true);

                    var isValid = m.isValid();

                    //console.log(value);
                    //console.log(isValid);

                    return isValid;

                };

                ngModel.$parsers.push(function(value) {

                    if (!value || value.length === 0) {
                         return value;
                    };

                    if (isDate(value)) {
                        ngModel.$setValidity('myDate', true);
                    } else {
                        ngModel.$setValidity('myDate', false);
                    }

                    return value;

                });

            }
        }
    }
);

HTML

<div class="form-group">
    <label for="myDateExample">My Date Example</label>
    <input id="myDateExample"
           name="myDateExample"
           class="form-control"
           required=""
           my-date
           maxlength="50"
           ng-model="myModel.myDateExample"
           type="text" />
    <div ng-messages="myForm.myDateExample.$error" ng-if="myForm.$submitted || myForm.myDateExample.$touched" class="errors">
        <div ng-messages-include="template/validation/messages.html"></div>
    </div>
</div>

template / validation / messages.html

<div ng-message="required">Required Field</div>
<div ng-message="number">Must be a number</div>
<div ng-message="email">Must be a valid email address</div>
<div ng-message="minlength">The data entered is too short</div>
<div ng-message="maxlength">The data entered is too long</div>
<div ng-message="myDate">Must be a valid date</div>

1

Angularjs ui bootstrap คุณสามารถใช้ angularjs ui bootstrap มันให้การตรวจสอบวันที่ด้วย

<input type="text"  class="form-control" 
datepicker-popup="{{format}}" ng-model="dt" is-open="opened" 
min-date="minDate" max-date="'2015-06-22'"  datepickeroptions="dateOptions"
date-disabled="disabled(date, mode)" ng-required="true"> 



ในตัวควบคุมสามารถระบุรูปแบบใดก็ได้ที่คุณต้องการแสดงวันที่เป็น datefilter

$ scope.formats = ['dd-MMMM-yyyy', 'yyyy / MM / dd', 'dd.MM.yyyy', 'shortDate'];


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