web-dev-qa-db-fra.com

Le modèle n'est pas un objet de date lors de la saisie dans AngularJS

En utilisant AngularJS, je tente d’afficher une date à l’aide d’une entrée type=date:

<input ng-model="campaign.date_start" type="date">

Cependant, cela donne l'erreur suivante:

Error: error:datefmt
Model is not a date object

La date provient en fait d'une API JSON au format suivant:

date_start": "2014-11-19"

J'ai pensé que je pouvais le résoudre en utilisant un filtre, mais cela n'a pas fonctionné et j'obtiens la même erreur avec:

 <input ng-model="campaign.date_start | date" type="date">

J'ai aussi essayé de convertir la chaîne en une date, mais j'obtiens encore la même erreur:

 $scope.campaign.date_start = Date(campaign.date_start);

Que puis-je essayer?

31
Prometheus

Vous devez instancier campaign.date_start avec Date pour ne pas l'utiliser comme une fonction.

Cela devrait ressembler à quelque chose comme ça (petite démo):

$scope.campaign.date_start = new Date(campaign.date_start);
21
ryeballar

Vous pouvez utiliser cette directive.

angular.module('app')
.directive("formatDate", function(){
  return {
   require: 'ngModel',
    link: function(scope, elem, attr, modelCtrl) {
      modelCtrl.$formatters.Push(function(modelValue){
        return new Date(modelValue);
      })
    }
  }
})

Dans votre html;

<input type="date" ng-model="date" format-date>

$formatters

Array.<Function> 

Tableau de fonctions à exécuter, en tant que pipeline, chaque fois que la valeur du modèle change. Les fonctions sont appelées dans l'ordre inverse, chacune transmettant la valeur à la suivante. La dernière valeur renvoyée est utilisée comme valeur DOM actuelle. Utilisé pour formater/convertir les valeurs à afficher dans le contrôle.

41
cs1707

La directive de cs1707 est excellente, sauf si la valeur de la portée de la date est null ou undefined, elle initialisera une date avec 1/1/1970. Ce n'est probablement pas optimal pour la plupart des gens

Ci-dessous, une version modifiée de la directive cs1707 qui laissera un modèle null/undefined tel quel:

angular.module('app').directive("formatDate", function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attr, modelCtrl) {
            modelCtrl.$formatters.Push(function(modelValue) {
                if (modelValue){
                    return new Date(modelValue);
                }
                else {
                    return null;
                }
            });
        }
    };
});

Dans votre html;

<input type="date" ng-model="date" format-date>

Une autre option

Si vous souhaitez que cela s'applique à toutes les entrées de type date, il n'est pas nécessaire d'ajouter l'attribut format-date à chaque élément d'entrée. Vous pouvez utiliser la directive suivante. (Soyez prudent avec cela, car il pourrait interagir avec d'autres directives personnalisées de manière inattendue.)

angular.module('app').directive("input", function() {
    return {
        require: 'ngModel',
        link: function(scope, elem, attr, modelCtrl) {
            if (attr['type'] === 'date'){
                modelCtrl.$formatters.Push(function(modelValue) {
                    if (modelValue){
                        return new Date(modelValue);
                    }
                    else {
                        return null;
                    }
                });
            }

        }
    };
});

Dans votre html;

<input type="date" ng-model="date">
6
Jakobovski

Une autre solution directive ici:

//inside directives.js
.directive('dateField', function () {
    return {
        restrict: ' E',
        scope: {
            ngBind: '=ngModel',
            ngLabel: '@'
        },
        replace: true,
        require: 'ngModel',
        controller: function ($scope) {
            if ($scope.ngBind != null) {
                var pattern = /Date\(([^)]+)\)/;
                var results = pattern.exec($scope.ngBind);
                var dt = new Date(parseFloat(results[1]));
                $scope.ngBind = dt;
            };
        },
        templateUrl: 'templates/directives/dateField.html'
    }
})
;

Ajoutez un modèle de directive comme ceci:

<!-- app.directives templates/directives/dateField -->
<script id="templates/directives/dateField.html" type="text/ng-template">    
    <label class="item item-input item-stacked-label ">
        <span class="input-label">{{ngLabel}}</span>
        <input type="date" placeholder="" ng-model="ngBind" />
    </label>
</script>

Et l'utiliser 

<date-field ng-label="This date..." ng-model="datajson.do.date"></date-field>

Bonne chance!

1
kcho0

Utilisation de la directive pour réinitialiser les formateurs/analyseurs angulaires par défaut de ngModelCtrl.$formatters.length = 0; ngModelCtrl.$parsers.length = 0;

Cela fonctionne pour input[type="date"] ainsi que input[type="time"]. Fonctionne également bien pour l'application Cordova

HTML:

<input date-input type="time" ng-model="created_time">

Directive angulaire:

app.directive('dateInput', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attr, ngModelCtrl) {
            //Angular 1.3 insert a formater that force to set model to date object, otherwise throw exception.
            //Reset default angular formatters/parsers
            ngModelCtrl.$formatters.length = 0;
            ngModelCtrl.$parsers.length = 0;
        }
    };
});
0
jafarbtech

Une autre manière simple en utilisant une directive: 

HTML: 

<input date-input type="time" ng-model="created_time">

Directif:

app.directive('dateInput', function(){
    return {
        restrict : 'A',
        scope : {
            ngModel : '='
        },
        link: function (scope) {
            if (scope.ngModel) scope.ngModel = new Date(scope.ngModel);
        }
    }
});

Vous pouvez éviter cette erreur en utilisant cette partie de code qui est en fait une erreur de format de date pendant que nous passons notre date à une fonction ou à une API.

            var options = {
                weekday: "long", year: "numeric", month: "short",
                day: "numeric", hour: "2-digit", minute: "2-digit"
            };
            $scope.campaign.date_start = $scope.campaign.date_start.toLocaleTimeString("en-us", options);

où en-us format = vendredi 1 février 2013 06h00 J'espère que cela aidera les autres à résoudre le problème, je faisais face à une telle erreur et je le résolus avec cela.

0
Usman