Angular формат даты datepicker начальной загрузки не форматирует значение ng-модели

Я использую средство выбора даты начальной загрузки в своем приложении angular. Однако, когда я выбираю дату из этого средства выбора даты, лежащего в основе ng-модели, которую я привязываю, обновляется, я хочу, чтобы эта ng-модель была в одном формате даты «MM / dd / yyyy». но он каждый раз делает такое свидание

"2009-02-03T18:30:00.000Z"

вместо того

02/04/2009

Я создал plunkr для той же ссылки plunkr

Мой код Html и контроллера показан ниже

<!doctype html>
<html ng-app="plunker">
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
    <script src="example.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>

<div ng-controller="DatepickerDemoCtrl">
    <pre>Selected date is: <em>{{dt | date:'MM/dd/yyyy' }}</em></pre>
    <p>above filter will just update above UI but I want to update actual ng-modle</p>


    <h4>Popup</h4>
    <div class="row">
        <div class="col-md-6">
            <p class="input-group">
              <input type="text" class="form-control"
              datepicker-popup="{{format}}" 
              ng-model="dt"
              is-open="opened" min-date="minDate"
              max-date="'2015-06-22'" 
              datepicker-options="dateOptions" 
              date-disabled="disabled(date, mode)" 
              ng-required="true" close-text="Close" />
              <span class="input-group-btn"> 
                <button type="button" class="btn btn-default" ng-click="open($event)">
                <i class="glyphicon glyphicon-calendar"></i></button>
              </span>
            </p>
        </div>
    </div>
    <!--<div class="row">
        <div class="col-md-6">
            <label>Format:</label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
        </div>
    </div>-->

    <hr />
    {{dt}}
</div>
  </body>
</html>

Контроллер Angular

angular.module('plunker', ['ui.bootstrap']);
var DatepickerDemoCtrl = function ($scope) {


  $scope.open = function($event) {
    $event.preventDefault();
    $event.stopPropagation();

    $scope.opened = true;
  };

  $scope.dateOptions = {
    formatYear: 'yy',
    startingDay: 1
  };


  $scope.format = 'dd-MMMM-yyyy';
};

Заранее благодарим за просмотр моего вопроса.

ОБНОВЛЕНИЕ

Я вызываю ниже метод публикации моих данных, а VAR - это массив размером 900, который содержит переменные выбора даты.

public SaveCurrentData(formToSave: tsmodels.ResponseTransferCalculationModelTS) {

        var query = this.EntityQuery.from('SaveFormData').withParameters({
            $method: 'POST',
            $encoding: 'JSON',
            $data: {
                VAR: formToSave.VAR,
                X: formToSave.X,
                CurrentForm: formToSave.currentForm,
            }
        });

        var deferred = this.q.defer();

        this.manager.executeQuery(query).then((response) => {
            deferred.resolve(response);
        }, (error) => {
                deferred.reject(error);
            });

        return deferred.promise;
    }

person Jenish Rabadiya    schedule 13.06.2014    source источник
comment
Лол, повезло, что ты мой даже не привязался к моей ng-модели, я скопировал твой код, и он работает для меня. :)   -  person user3718908    schedule 17.09.2015


Ответы (13)


Хотя были опубликованы похожие ответы, я хотел бы внести свой вклад в то, что мне показалось самым простым и чистым исправлением. Предполагая, что вы используете DatePicker AngularUI и ваше начальное значение для ng-Model не форматируется, просто добавление следующей директивы в ваш проект решит проблему:

angular.module('yourAppName')
.directive('datepickerPopup', function (){
    return {
        restrict: 'EAC',
        require: 'ngModel',
        link: function(scope, element, attr, controller) {
      //remove the default formatter from the input directive to prevent conflict
      controller.$formatters.shift();
  }
}
});

Я нашел это решение в проблемах Github AngularUI, и поэтому вся заслуга принадлежит людям.

person stefan2k    schedule 16.12.2014
comment
За это нужно проголосовать больше, чем за принятый ответ, особенно при использовании bower или pkg manager для получения angular -ui. Работает отлично, и я могу оставить angular -ui.js в покое. - person notbrain; 13.02.2015
comment
Я согласен - этот ответ намного лучше, особенно когда вы используете предварительно минифицированный код из пакета nuget. Ручное редактирование означает, что вам нужно воссоздавать их каждый раз, когда вы обновляете код, хотя это постоянно и просто - и если эта ошибка будет исправлена, вы просто удалите директиву. Это, безусловно, лучший ответ. - person cidthecoatrack; 21.02.2015
comment
Я пару дней поигрался с моими типами даты sql, форматированием и т. Д., Чтобы заставить эту вещь работать. Этот ответ сразу исправил это. аргггг! лол время, я никогда не вернусь ... - person jenki221; 29.05.2015
comment
Работал у меня. Большое спасибо! - person John; 19.06.2015
comment
Не работал у меня на angular 1.4 с angular-bootstrap 0.13.3. этот ответ сделал! - person Tom Bevelander; 04.09.2015
comment
У меня работал с Angular 1.6.5 и начальной загрузкой 0.12. Спасибо, что доставили это в SO. Очень элегантное решение. - person Kevin; 20.07.2017

Вы можете использовать парсеры $, как показано ниже, это решило проблему для меня.

window.module.directive('myDate', function(dateFilter) {
  return {
    restrict: 'EAC',
    require: '?ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$parsers.push(function(viewValue) {
        return dateFilter(viewValue,'yyyy-MM-dd');
      });
    }
  };
});

HTML:

<p class="input-group datepicker" >
  <input
     type="text"
     class="form-control"
     name="name"
     datepicker-popup="yyyy-MM-dd"
     date-type="string"
     show-weeks="false"
     ng-model="data[$parent.editable.name]" 
     is-open="$parent.opened"
     min-date="minDate"
     close-text="Close"
     ng-required="{{editable.mandatory}}"
     show-button-bar="false"
     close-on-date-selection="false"
     my-date />
  <span class="input-group-btn">
    <button type="button" class="btn btn-default" ng-click="openDatePicker($event)">
      <i class="glyphicon glyphicon-calendar"></i>
    </button>
  </span>
</p>
person Rishab777    schedule 28.01.2015
comment
Это исправление для Angular 1.4 и angular bootstrap .13, приведенное выше не работает - person Tom Bevelander; 04.09.2015
comment
Ваше решение работает вместо решения, получившего наибольшее количество голосов. Angular1.4.7 UI-bootstrap 0.14.3 - person jchnxu; 20.11.2015

Я столкнулся с той же проблемой, и после пары часов регистрации и исследования я исправил ее.

Оказалось, что впервые значение устанавливается в средстве выбора даты, $ viewValue представляет собой строку, поэтому dateFilter отображает ее как есть. Все, что я сделал, это преобразовал его в объект Date.

Найдите этот блок в файле ui-bootstrap-tpls

  ngModel.$render = function() {
    var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
    element.val(date);

    updateCalendar();
  };

и замените его на:

  ngModel.$render = function() {
    ngModel.$viewValue = new Date(ngModel.$viewValue);
    var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
    element.val(date);

    updateCalendar();
  };

Надеюсь, это поможет :)

person christina    schedule 17.10.2014
comment
если (! ngModel. $ viewValue) ngModel. $ viewValue = new Date (); иначе ngModel. $ viewValue = новая дата (ngModel. $ viewValue); - person christina; 20.10.2014
comment
Немного лучше исправить в github.com/angular-ui/bootstrap/pull/2943, который обрабатывает случай, когда значение равно null. - person Kris Braun; 30.12.2014
comment
Это не работает, если вы используете angular-bootstrap из bower или другого менеджера пакетов. Редактировать саму библиотеку не рекомендуется. - person notbrain; 13.02.2015

format, указанный через datepicker-popup, - это просто формат отображаемой даты. Базовый ngModel - это объект Date. Попытка отобразить его покажет его представление по умолчанию, соответствующее стандарту.

Вы можете отобразить его как хотите, используя фильтр date в представлении, или, если вам нужно, чтобы он был проанализирован в контроллере, вы можете ввести $filter в свой контроллер и называть его как $filter('date')(date, format). См. Также документы о фильтрах дат.

person link    schedule 13.06.2014
comment
да, я понял вашу точку зрения. Но я динамически генерирую средства выбора даты на экране, поэтому нет места для анализа этой ng-модели. - person Jenish Rabadiya; 13.06.2014
comment
Хорошо, но где вы хотите использовать ngModel из указателя даты? Если это для отображения в пользовательском интерфейсе, просто используйте date. Если он находится в службе / контроллере, просто используйте $filter('date'). - person link; 13.06.2014
comment
На самом деле мой ngModel имеет длинный массив, который отправляется в службу REST. - person Jenish Rabadiya; 13.06.2014
comment
Теперь я думаю, мне следует создать свою собственную директиву, которая будет содержать всплывающее окно datepicker в шаблоне и будет анализировать базовый объект даты в желаемом формате. - person Jenish Rabadiya; 13.06.2014
comment
Но в конечном итоге вы также будете использовать фильтр или средство форматирования в своей собственной директиве, я не понимаю, как вы этого избежите. Не могли бы вы подготовить скрипку, которая покажет, как вы используете дату из датпикера? - person link; 13.06.2014
comment
Наконец-то я получил решение. Посмотрите мой ответ stackoverflow.com/questions/24198669/ - person Jenish Rabadiya; 18.06.2014

Вы можете использовать средства форматирования после выбора значения в директиве datepicker. Например

angular.module('foo').directive('bar', function() {
    return {
        require: '?ngModel',
        link: function(scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            ctrl.$formatters.push(function(value) {
                if (value) {
                    // format and return date here
                }

                return undefined;
            });
        }
    };
});

ССЫЛКА.

person Miraage    schedule 16.06.2014
comment
да, это то, что я говорю о преобразовании ссылки в приведенном выше ответе. но мне нужно использовать синтаксический анализатор для обновления базовой ng-модели, и если бы я реализовал синтаксический анализатор, который обновляет ng-модель, он мог бы снова вызвать директиву выбора даты для обновления даты. Я не уверен в этом, но попробую. - person Jenish Rabadiya; 16.06.2014
comment
Наконец-то я получил решение. Посмотрите мой ответ stackoverflow.com/questions/24198669/ - person Jenish Rabadiya; 18.06.2014
comment
Вы на правильном пути, но я считаю, что это должен быть ctrl. $ Parsers.push, поскольку он хочет, чтобы его ng-модель сохраняла измененное значение. - person mikelt21; 16.12.2014

С таким количеством ответов уже написано, вот мое мнение.

С Angular 1.5.6 и ui-bootstrap 1.3.3 просто добавьте это в модель, и все готово.

ng-model-options="{timezone: 'UTC'}" 

Примечание. Используйте это только в том случае, если вас беспокоит, что дата отстает на 1 день, и вас не беспокоит дополнительное время T00: 00: 00.000Z.

Обновленный Plunkr здесь:

http://plnkr.co/edit/nncmB5EHEUkZJXRwz5QI?p=preview

person Abdul Rehman Sayed    schedule 16.06.2016

Все предложенные решения у меня не работали, но самое близкое было от @Rishii.

Я использую AngularJS 1.4.4 и UI Bootstrap 0.13.3.

.directive('jsr310Compatible', ['dateFilter', 'dateParser', function(dateFilter, dateParser) {
  return {
    restrict: 'EAC',
    require: 'ngModel',
    priority: 1,
    link: function(scope, element, attrs, ngModel) {
      var dateFormat = 'yyyy-MM-dd';

      ngModel.$parsers.push(function(viewValue) {
        return dateFilter(viewValue, dateFormat);
      });

      ngModel.$validators.date = function (modelValue, viewValue) {
        var value = modelValue || viewValue;

        if (!attrs.ngRequired && !value) {
          return true;
        }

        if (angular.isNumber(value)) {
          value = new Date(value);
        }

        if (!value) {
          return true;
        }
        else if (angular.isDate(value) && !isNaN(value)) {
          return true;
        }
        else if (angular.isString(value)) {
          var date = dateParser.parse(value, dateFormat);
          return !isNaN(date);
        }
        else {
          return false;
        }
      };
    }
  };
}])
person Ludovic Guillaume    schedule 01.09.2015

Я могу исправить это, добавив код ниже в свой файл JSP. Теперь значения модели и пользовательского интерфейса совпадают.

<div ng-show="false">
    {{dt = (dt | date:'dd-MMMM-yyyy') }}
</div>  
person Rajesh Dave    schedule 02.11.2015
comment
Мне кажется, что ваша проблема сильно отличается от того, что было упомянуто выше (вопрос). В приведенном выше вопросе указывается, что существует проблема, когда для бэкэнд-модели требуется какой-то другой тип, кроме даты, и то, что вы хотите, похоже, показывает что-то другое в пользовательском интерфейсе. Помните, что для вашей модели серверной части решения будет использоваться тот же объект даты. - person Jenish Rabadiya; 02.11.2015

Шаги по изменению формата даты по умолчанию для ng-модели

Для разных форматов даты проверьте здесь значения формата даты jqueryui datepicker, например, я использовал dd / mm / yy

Создать директиву angularjs

angular.module('app', ['ui.bootstrap']).directive('dt', function () {
return {
    restrict: 'EAC',
    require: 'ngModel',
    link: function (scope, element, attr, ngModel) {
        ngModel.$parsers.push(function (viewValue) {
           return dateFilter(viewValue, 'dd/mm/yy');
        });
    }
 }
});

Запись dateFilter функция

function dateFilter(val,format) {
    return $.datepicker.formatDate(format,val);
}

На странице html напишите атрибут ng-modal

<input type="text" class="form-control" date-type="string"  uib-datepicker-popup="{{format}}" ng-model="src.pTO_DATE" is-open="popup2.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" show-button-bar="false" show-weeks="false" dt />
person Sumit Jambhale    schedule 12.01.2016

Директива datepicker (и datepicker-popup) требует, чтобы ng-модель была объектом Date. Это задокументировано здесь.

Если вы хотите, чтобы ng-model была строкой в ​​определенном формате, вам следует создать директиву-оболочку. Вот пример (Plunker):

(function () {
    'use strict';

    angular
        .module('myExample', ['ngAnimate', 'ngSanitize', 'ui.bootstrap'])
        .controller('MyController', MyController)
        .directive('myDatepicker', myDatepickerDirective);

    MyController.$inject = ['$scope'];

    function MyController ($scope) {
      $scope.dateFormat = 'dd MMMM yyyy';
      $scope.myDate = '30 Jun 2017';
    }

    myDatepickerDirective.$inject = ['uibDateParser', '$filter'];

    function myDatepickerDirective (uibDateParser, $filter) {
        return {
            restrict: 'E',
            scope: {
                name: '@',
                dateFormat: '@',
                ngModel: '='
            },
            required: 'ngModel',
            link: function (scope) {

                var isString = angular.isString(scope.ngModel) && scope.dateFormat;

                if (isString) {
                    scope.internalModel = uibDateParser.parse(scope.ngModel, scope.dateFormat);
                } else {
                    scope.internalModel = scope.ngModel;
                }

                scope.open = function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    scope.isOpen = true;
                };

                scope.change = function () {
                    if (isString) {
                        scope.ngModel = $filter('date')(scope.internalModel, scope.dateFormat);
                    } else {
                        scope.ngModel = scope.internalModel;
                    }
                };

            },
            template: [
                '<div class="input-group">',
                    '<input type="text" readonly="true" style="background:#fff" name="{{name}}" class="form-control" uib-datepicker-popup="{{dateFormat}}" ng-model="internalModel" is-open="isOpen" ng-click="open($event)" ng-change="change()">',
                    '<span class="input-group-btn">',
                        '<button class="btn btn-default" ng-click="open($event)">&nbsp;<i class="glyphicon glyphicon-calendar"></i>&nbsp;</button>',
                    '</span>',
                '</div>'
            ].join('')
        }
    }

})();
<!DOCTYPE html>
<html>

  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
    <script src="example.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  </head>

  <body ng-app="myExample">
    <div ng-controller="MyController">
      <p>
        Date format: {{dateFormat}}
      </p>
      <p>
        Value: {{myDate}}
      </p>
      <p>
        <my-datepicker ng-model="myDate" date-format="{{dateFormat}}"></my-datepicker>
      </p>
    </div>
  </body>

</html>

person user147677    schedule 23.06.2017

Определение новой директивы для обхода ошибки на самом деле не идеально.

Поскольку средство выбора даты правильно отображает более поздние даты, одним из простых способов решения проблемы может быть просто установка переменной модели сначала на null, а затем на текущую дату через некоторое время:

$scope.dt = null;
$timeout( function(){
    $scope.dt = new Date();
},100);
person gm2008    schedule 27.04.2017

После проверки приведенных выше ответов я пришел к этому, и он отлично работал, без необходимости добавлять дополнительный атрибут в вашу разметку.

angular.module('app').directive('datepickerPopup', function(dateFilter) {
    return {
        restrict: 'EAC',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {
            ngModel.$parsers.push(function(viewValue) {
                return dateFilter(viewValue, 'yyyy-MM-dd');
            });
        }
    }
});
person Dennis Mwangangi    schedule 16.04.2018

Наконец, я решил проблему, указанную выше. angular-strap имеет ту же функцию, которую я ожидал. Просто применив date-format="MM/dd/yyyy" date-type="string", я получил ожидаемое поведение обновления ng-модели в заданном формате.

<div class="bs-example" style="padding-bottom: 24px;" append-source>
    <form name="datepickerForm" class="form-inline" role="form">
      <!-- Basic example -->
      <div class="form-group" ng-class="{'has-error': datepickerForm.date.$invalid}">
        <label class="control-label"><i class="fa fa-calendar"></i> Date <small>(as date)</small></label>
        <input type="text"  autoclose="true"  class="form-control" ng-model="selectedDate" name="date" date-format="MM/dd/yyyy" date-type="string" bs-datepicker>
      </div>
      <hr>
      {{selectedDate}}
     </form>
</div>

вот рабочая ссылка

person Jenish Rabadiya    schedule 18.06.2014
comment
так вам пришлось перейти на angular-strap вместо ui.bootstrap? В ui.bootstrap нет подобной опции? - person Matt Pileggi; 21.10.2014
comment
@MattPileggi На самом деле я не нашел. Буду признателен, если вы найдете то же самое с ui.bootstrap и поделитесь им здесь. - person Jenish Rabadiya; 22.10.2014
comment
Для этого решения требуется датапикер angular-strap. Это связано с другими проблемами. - person Sergiu Paraschiv; 13.01.2015
comment
@SergiuParaschiv, но в моем случае он работал нормально. вы можете сослаться на плункер. - person Jenish Rabadiya; 13.01.2015
comment
вы не ответили на исходный вопрос - как заставить это работать с начальной загрузкой angular -ui. Вы должны принять ответ Кристины ниже, поскольку он фактически отвечает на исходный вопрос. - person John; 21.01.2015
comment
@John Я полностью с тобой согласен. Переключен принятый ответ. - person Jenish Rabadiya; 22.01.2015