web-dev-qa-db-fra.com

Le format de date d'amorce angulaire de datepicker ne formate pas la valeur de ng-model

J'utilise bootstrap date-picker dans mon application angulaire. Cependant, lorsque je sélectionne une date à partir de ce modèle ng sous-jacent du sélecteur de date que je lie, celle-ci est mise à jour, je souhaite que ce modèle soit dans un format de date 'MM/jj/aaaa'. mais chaque fois fait date comme ça 

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

au lieu de 

02/04/2009

J'ai créé un plunkr pour le même lien plunkr

Mon code HTML et de contrôleur est comme ci-dessous

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

Contrôleur angulaire

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

Merci d'avance pour revoir ma question.

METTRE &AGRAVE; JOUR

J'appelle la méthode ci-dessous pour publier mes données et VAR est un tableau de taille 900 contenant des variables de sélecteur de date. 

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;
    }
61
Jenish Rabadiya

Bien que des réponses similaires aient été postées, j'aimerais apporter ce qui semblait être la solution la plus facile et la plus propre pour moi. En supposant que vous utilisiez le datepicker AngularUI et que la valeur initiale de ng-Model ne soit pas formatée, le simple fait d'ajouter la directive suivante à votre projet résoudra le problème:

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

J'ai trouvé cette solution dans les problèmes de Github AngularUI et donc tout le mérite revient aux gens là-bas.

101
stefan2k

Vous pouvez utiliser les analyseurs $ comme ci-dessous, cela a résolu le problème.

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

J'ai rencontré le même problème et après quelques heures d'enregistrement et d'enquête, je l'ai résolu.

Il s'est avéré que pour la première fois que la valeur est définie dans un sélecteur de date, $ viewValue est une chaîne de sorte que dateFilter l'affiche telle quelle. Tout ce que j'ai fait est de l'analyser dans un objet Date.

Recherchez ce bloc dans le fichier ui-bootstrap-tpls

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

    updateCalendar();
  };

et le remplacer par:

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

    updateCalendar();
  };

Espérons que cela aidera :)

13
christina

La format spécifiée par le datepicker-popup n'est que le format de la date affichée. La variable ngModel sous-jacente est un objet Date. Essayer de l'afficher montrera qu'il s'agit de sa représentation par défaut conforme à la norme.

Vous pouvez l'afficher à votre guise en utilisant le filtre date dans la vue ou, si vous souhaitez qu'il soit analysé dans le contrôleur, vous pouvez injecter $filter dans votre contrôleur et l'appeler par $filter('date')(date, format). Voir aussi la documentation du filtre date .

9
link

Vous pouvez utiliser des outils de formatage après avoir sélectionné une valeur dans votre directive 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;
            });
        }
    };
});

LIEN .

5
Miraage

Avec tant de réponses déjà écrites, voici mon point de vue. 

Avec Angular 1.5.6 et ui-bootstrap 1.3.3, ajoutez simplement ceci sur le modèle et vous avez terminé.

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

Note: utilisez-le uniquement si vous craignez que la date ne soit pas retardée d'un jour et ne vous inquiétez pas du temps supplémentaire T00: 00: 00.000Z 

Plunkr mis à jour ici: 

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

4
Abdul Rehman Sayed

Toutes les solutions proposées ne fonctionnaient pas pour moi, mais la plus proche venait de @Rishii.

J'utilise AngularJS 1.4.4 et l'interface utilisateur 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;
        }
      };
    }
  };
}])
3
Ludovic Guillaume

Je peux résoudre ce problème en ajoutant le code ci-dessous dans mon fichier JSP. Maintenant, les valeurs du modèle et de l'interface utilisateur sont identiques.

<div ng-show="false">
    {{dt = (dt | date:'dd-MMMM-yyyy') }}
</div>  
1
Rajesh Dave

Étapes pour changer le format de date par défaut de ng-model

Pour différents formats de date, vérifiez les valeurs de format de date jqueryui Datepicker ici, par exemple, j’ai utilisé jj/mm/aa

Créer une directive 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');
        });
    }
 }
});

Ecrire la fonction dateFilter

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

Dans la page html, écrivez l'attribut 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 />
1
Sumit Jambhale

La directive datepicker (et datepicker-popup) requiert que le modèle ng soit un objet Date. Ceci est documenté ici .

Si vous souhaitez que ng-model soit une chaîne au format spécifique, vous devez créer une directive wrapper. Voici un exemple ( 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>

0
user147677

Définir une nouvelle directive pour contourner un bogue n'est pas vraiment idéal. 

Étant donné que le sélecteur de date affiche correctement les dates ultérieures, une solution de contournement simple consiste à définir d'abord la variable de modèle sur null, puis sur la date actuelle après un certain temps: 

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

Enfin, j'ai une excellente solution au problème ci-dessus. angular-strap a exactement les mêmes caractéristiques que celles que j'attendais. En appliquant simplement date-format="MM/dd/yyyy" date-type="string", j'ai eu le comportement attendu de la mise à jour de ng-model dans un format donné.

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

ici fonctionne plunk link

0
Jenish Rabadiya

Après avoir vérifié les réponses ci-dessus, j'ai trouvé cela et cela fonctionnait parfaitement sans avoir à ajouter d'attribut supplémentaire à votre balise

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