Làm cách nào để định dạng ngày bằng ng-model?


93

Tôi có một đầu vào được xác định là

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

Được thiết lập để hiển thị ở những nơi khác trên trang:

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

Khi trang tải, ngày sinh sẽ được định dạng độc đáo như sau Dec 22, 2009. Tuy nhiên, khi tôi nhìn vào bên trong, <input>nó được hiển thị Tue Dec 22 2009 00:00:00 GMT-0800 (Pacific Standard Time)mà tôi đoán là cách JS hiển thị Datecác đối tượng dưới dạng chuỗi.

Thứ nhất, làm cách nào để tôi yêu cầu Angular hiển thị ngày tháng <input>như thế 12/22/2009nào? Tôi dường như không thể áp dụng |filtersbên trong ng-modelthuộc tính.

Thứ hai, ngay sau khi tôi chỉnh sửa ngày, thậm chí giữ nó ở định dạng ban đầu, văn bản khác của tôi (bên trong <td>) dường như không áp dụng |datebộ lọc nữa; nó đột ngột thay đổi định dạng để khớp với định dạng của hộp văn bản đầu vào. Làm cách nào để tôi áp dụng |datebộ lọc mỗi khi mô hình thay đổi?


Câu hỏi liên quan:


Tôi cũng gặp sự cố về điều đó, nhưng đã có giải pháp đơn giản hơn bằng cách sử dụng các Date()hàm js tiêu chuẩn : $scope.departDate = new Date(); $scope.departTime = $scope.departDate.toTimeString().slice(0, 5);Và không cần các bộ lọc khác hoặc cách giải quyết phức tạp trong AngularJS IMO.
boldnik

Câu trả lời:


71

Sử dụng xác thực tùy chỉnh của biểu mẫu http://docs.angularjs.org/guide/forms Demo: http://plnkr.co/edit/NzeauIDVHlgeb6qF75hX?p=preview

Chỉ thị sử dụng trình định dạng và phân tích cú pháp và 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
Tôi muốn tạo một ví dụ nhỏ về trình định dạng và phân tích cú pháp, Cảm ơn câu hỏi của bạn hôm nay, tôi có lý do để làm điều đó.
SunnyShah

1
@Mark, Đã khắc phục sự cố Nan trong trò chơi thứ hai. ;)
SunnyShah

1
Đã xóa cách tiếp cận thứ hai. Nó quá lỗi.
SunnyShah

1
Bạn có thể sử dụng lệnh on-change để thực hiện các cải tiến hơn nữa. stackoverflow.com/questions/14477904/…
SunnyShah

7
@SunnyShah - công cụ tuyệt vời, thực sự hữu ích, cảm ơn rất nhiều. Tôi đã tự hỏi tại sao bạn có var dateFormat = attrs.moMediumDate;và không var dateFormat = attrs.moDateInput;moMediumDate dường như không được đặt ở bất kỳ đâu vì vậy nếu các đầu vào không được tạo động, một định dạng ban đầu sẽ không bao giờ được chọn.
toxaq

37

Đây là hướng dẫn góc ngày giờ rất tiện dụng . Bạn có thể sử dụng nó như thế này:

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

Nó cũng thêm mặt nạ vào đầu vào của bạn và thực hiện xác nhận.


1
Tôi cũng đã sử dụng chỉ thị này, cảm ơn. Nếu bạn đang sử dụng nó với jQuery UI Datepicker, bạn phải đảm bảo rằng định dạng được chỉ định trong datetime="<format>"giá trị thuộc tính khớp với định dạng được chỉ định trong dateFormattùy chọn Datepicker .
tylerwal

1
Tôi tự hỏi làm thế nào mà có thể có một giải pháp hoàn hảo ở đây chỉ với vài phiếu bầu. Quá nhiều cho các cuộc hẹn hò, và bạn có thể giải quyết chúng ngay tại đây, ngay bây giờ! Cảm ơn anh bạn.
C0ZEN

2
Tôi chắc chắn rằng nhiều người sẽ bỏ phiếu cho điều này, nếu tài liệu được cải thiện để giúp đưa vào ứng dụng góc cạnh hiện có dễ dàng hơn.
Joel Hansen

8

Tôi đã tạo một chỉ thị đơn giản để cho phép các input[type="date"]phần tử biểu mẫu chuẩn hoạt động chính xác với AngularJS ~ 1.2.16.

Xem tại đây: https://github.com/betsol/angular-input-date

Và đây là bản demo: http://jsfiddle.net/F2LcY/1/


Này @Lorenzo, ý bạn là gì? Bạn có thể giải thích thêm được không?
Slava Fomin II

Ngày tháng trong năm bằng tiếng Pháp như Lun Mar Mer cho Mon Tue, Wen
Merlin

@Lorenzo Tôi không chắc mình không đủ sức chịu đựng. Chỉ thị không liên quan gì đến bản địa hóa. Có thể chức năng định dạng bạn đang sử dụng đang sử dụng cài đặt ngôn ngữ từ trình duyệt / hệ thống của bạn. Nếu bạn cung cấp một ví dụ, tôi sẽ có thể giúp đỡ (jsfiddle).
Slava Fomin II

1
chỉ hỗ trợ chrome, quá tệ.
Gemini:

Mục tiêu của chỉ thị là hỗ trợ tất cả các nền tảng. Nếu bạn gặp sự cố với nó, tại sao bạn không tạo sự cố trên repo GitHub? Tôi luôn đáp ứng mọi vấn đề.
Slava Fomin II,

7

Tôi đang sử dụng trình chọn ngày jquery để chọn ngày. Ngày đọc chỉ thị của tôi và chuyển đổi nó sang định dạng ngày json (tính bằng mili giây) lưu trữ trong ng-modeldữ liệu trong khi hiển thị date được định dạng và ngược lại nếu ng-model có ngày json (tính bằng mili giây) hiển thị định dạng của tôi ở định dạng là jquery datepicker.

Mã HTML:

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

Chỉ thị Angular:

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'); 
            });

        }
    };
});

Ôi trời ơi!! Cảm ơn bạn rất nhiều !! Tôi thực sự đã tìm kiếm câu trả lời như thế này trong hai ngày, nhưng không thể tìm thấy câu trả lời nào! Bạn rock!
Michael Rentmeister

Tuyệt diệu. Tôi đã tìm kiếm một cái gì đó như thế này trong một thời gian. Tôi đang sử dụng materializecss cho giải pháp của mình. Nếu ai đó stubles thuận này và nhu cầu để chuyển đổi chỉ thị này cho materialize, chỉ trao đổi trên element.datepickervớielement.pickadate
IWI

7

Vì bạn đã sử dụng datepicker như một lớp nên tôi giả sử rằng bạn đang sử dụng datepicker Jquery hoặc thứ gì đó tương tự.

Có một cách để thực hiện những gì bạn đang có ý định mà không cần sử dụng moment.js, hoàn toàn chỉ sử dụng các lệnh datepicker và anglejs.

Tôi đã đưa ra một ví dụ ở đây trong Fiddle này

Trích đoạn fiddle ở đây:

  1. Datepicker có một định dạng khác và định dạng anglejs khác nhau, cần phải tìm kết quả phù hợp để ngày đó được chọn trước trong điều khiển và cũng được điền vào trường đầu vào khi ng-model bị ràng buộc. Định dạng dưới đây tương đương với 'mediumDate'định dạng của AngularJS.

    $(element).find(".datepicker")
              .datepicker({
                 dateFormat: 'M d, yy'
              }); 
  2. Chỉ thị nhập ngày cần phải có một biến chuỗi tạm thời để biểu thị dạng ngày có thể đọc được của con người.

  3. Việc làm mới trên các phần khác nhau của trang sẽ diễn ra thông qua các sự kiện, như $broadcast$on.

  4. Cũng có thể sử dụng bộ lọc để biểu diễn ngày ở dạng con người có thể đọc được trong ng-model nhưng với một biến mô hình tạm thời.

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

6

Tôi sử dụng lệnh sau đây khiến tôi và hầu hết người dùng rất hài lòng! Nó sử dụng thời điểm để phân tích cú pháp và định dạng. Nó trông hơi giống cái của SunnyShah, đã đề cập trước đó.

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

Trong biểu mẫu của tôi, tôi sử dụng nó như thế này:

<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>

Điều này sẽ liên kết một dấu thời gian (mili giây kể từ năm 1970) với doc.begindoc.end.


1
Thật dễ dàng để bỏ qua thực tế rằng, bên trong hàm liên kết này, ngModellà mã định danh tùy chỉnh của bạn cho đối số bộ điều khiển, không phải là tham chiếu trực tiếp, được đặt tên tới ngModel. Đây là một vị trí mà quy ước đặt tên mà arg 'ctrl' hoặc 'controller' giúp mọi thứ rõ ràng hơn và tránh nhầm lẫn.
XML

Cảm ơn! Tôi đã tìm kiếm cả ngày để tìm một cách hay để làm điều này. Thật không may, hầu hết các bản sửa lỗi khác liên quan đến việc chuyển sang trình chọn ngày được viết riêng cho góc cạnh và đó là quá nhiều công việc.
Josh Mouch

Tôi đã thử cả câu trả lời của bạn và @SunnyShah, nhưng câu trả lời của anh ấy dường như không hoạt động. Không chắc chắn lý do tại sao.
Josh Mouch

3

Trong Angular2 + cho bất kỳ ai quan tâm:

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

với loại bộ lọc trong DatePipe Angular.


Dang, tôi đang mắc kẹt trong AngularJS cũ mà tôi buộc phải làm việc, và tôi ghét nó! Ước gì tôi có những thứ trên để làm việc.
Jordan

2

Tôi thích để máy chủ trả về ngày tháng mà không cần sửa đổi và để javascript thực hiện việc xoa bóp chế độ xem. API của tôi trả về "MM / DD / YYYY hh: mm: ss" từ SQL Server.

Nguồn

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' }
        });
    }
);

Bộ điều khiển

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);
        }
    );
};

Chỉ thị xác thực 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 bạn có thể sử dụng Angularjs ui bootstrap, nó cũng cung cấp xác thực ngày tháng

<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"> 



trong bộ điều khiển có thể chỉ định bất kỳ định dạng nào bạn muốn để hiển thị ngày như datefilter

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


bạn không cần phải triển khai chỉ thị chỉ cho một trường đầu vào
P.JAYASRI
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.