J'ai une entrée de date au format HTML5 et j'aimerais que sa valeur soit définie par défaut sur la valeur de la propriété date de mon modèle. Le formatage ne me pose pas trop de problèmes, car Chrome semble en avoir décidé autrement en fonction de mes paramètres régionaux, mais idéalement, le format serait toujours dd/MM/yyyy
.
Voici comment j'ai configuré mon entrée:
<input type="date"
ng-model="date"
value="{{ date | date: 'yyyy-MM-dd' }}" />
Cela fonctionne bien sur Chrome et je vois par défaut ce qui suit:
(Je ne comprends toujours pas pourquoi la valeur doit être donnée dans yyyy-MM-dd
, si Chrome la formate toujours en fonction de mes paramètres régionaux, mais c'est une question différente.)
Mon problème est avec Firefox ne pas afficher la valeur de la date de la manière que j'ai spécifiée. Je pense que cela a à voir avec la liaison de l'entrée au modèle date
, parce que je peux spécifier à peu près n'importe quelle chaîne dans l'attribut value
, et je verrai toujours la chaîne de date longue dans l'entrée par défaut:
Si je supprime ng-model="date"
de la balise d’entrée, Firefox affiche joliment toutes les valeurs que je lui donne. Je ne pensais pas que le modèle auquel une entrée était liée avait réellement un effet sur sa valeur par défaut?
Je comprends que la saisie de date n'est pas prise en charge de manière universelle, mais vu qu'elle est supposée s'appuyer sur une saisie de texte simple, je ne vois pas pourquoi sa valeur ne serait pas simplement 2013-08-05
, comme spécifié par le filtre de date d'angular.
Alors, comment faire pour que Firefox accepte ma valeur formatée dans l'entrée de date?
NOTE Une fois les modifications effectuées par l'utilisateur, je vais bien sûr effectuer une validation et convertir chaque valeur entrée en date en un objet Date
approprié. Je ne suis pas sûr que cela soit pertinent pour la question, mais il faut l'indiquer au cas où, car les formats d'entrée auraient évidemment besoin d'être cohérents pour que la conversion de date fonctionne de la même manière dans tous les navigateurs. Problématique, bien sûr, avec Chrome qui décidait pour moi du format d'entrée ...
Le problème est que value
est ignoré lorsque ng-model
est présent .
Firefox, qui ne supporte pas actuellement type="date"
, convertira toutes les valeurs en chaîne. Puisque vous voulez (à juste titre) que date
soit un véritable objet Date
et non une chaîne, le meilleur choix est de créer une autre variable, par exemple dateString
, puis de lier les deux variables:
<input type="date" ng-model="dateString" />
function MainCtrl($scope, dateFilter) {
$scope.date = new Date();
$scope.$watch('date', function (date)
{
$scope.dateString = dateFilter(date, 'yyyy-MM-dd');
});
$scope.$watch('dateString', function (dateString)
{
$scope.date = new Date(dateString);
});
}
La structure actuelle est uniquement à des fins de démonstration. Vous feriez mieux de créer votre propre directive, notamment pour:
yyyy-MM-dd
,NgModelController#$formatters
et NgModelController#$parsers
plutôt que la variable artificielle dateString
(voir la documentation à ce sujet).Veuillez noter que j'ai utilisé yyyy-MM-dd
, car c'est un format directement pris en charge par l'objet JavaScript Date
. Si vous souhaitez en utiliser un autre, vous devez effectuer la conversion vous-même.
EDIT
Voici un moyen de faire une directive propre:
myModule.directive(
'dateInput',
function(dateFilter) {
return {
require: 'ngModel',
template: '<input type="date"></input>',
replace: true,
link: function(scope, Elm, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.unshift(function (modelValue) {
return dateFilter(modelValue, 'yyyy-MM-dd');
});
ngModelCtrl.$parsers.unshift(function(viewValue) {
return new Date(viewValue);
});
},
};
});
C'est une directive de base, il y a encore beaucoup à faire, par exemple:
yyyy-MM-dd
,Pourquoi la valeur devait être donnée en aaaa-MM-jj?
Selon le type d'entrée = date spéc de HTML 5, la valeur doit être au format yyyy-MM-dd
puisqu'elle prend le format d'un full-date
valide spécifié dans RFC3339 as
full-date = date-fullyear "-" date-month "-" date-mday
Il n'y a rien à faire avec Angularjs puisque l'entrée de directive ne supporte pas le type date
.
Comment faire en sorte que Firefox accepte ma valeur formatée lors de la saisie de la date?
FF ne prend pas en charge le type d'entrée date
pour au moins la version 24.0. Vous pouvez obtenir cette information de ici . Donc, pour le moment, si vous utilisez une entrée dont le type est date
dans FF, la zone de texte prend la valeur que vous transmettez.
Ma suggestion est que vous pouvez utiliser Timepicker d'angular-ui et ne pas utiliser le support HTML5 pour la saisie de la date.
Vous pouvez l'utiliser, cela fonctionne très bien:
<input type="date" class="form1"
value="{{date | date:MM/dd/yyyy}}"
ng-model="date"
name="id"
validatedateformat
data-date-format="mm/dd/yyyy"
maxlength="10"
id="id"
calendar
maxdate="todays"
ng-click="openCalendar('id')">
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar" ng-click="openCalendar('id')"></span>
</span>
</input>
Dans mon cas, j'ai résolu de cette façon:
$scope.MyObject = // get from database or other sources;
$scope.MyObject.Date = new Date($scope.MyObject.Date);
et la date de type d'entrée est ok
J'ai utilisé ng-change:
Date.prototype.addDays = function(days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
}
var app = angular.module('myApp', []);
app.controller('DateController', ['$rootScope', '$scope',
function($rootScope, $scope) {
function init() {
$scope.startDate = new Date();
$scope.endDate = $scope.startDate.addDays(14);
}
function load() {
alert($scope.startDate);
alert($scope.endDate);
}
init();
// public methods
$scope.load = load;
$scope.setStart = function(date) {
$scope.startDate = date;
};
$scope.setEnd = function(date) {
$scope.endDate = date;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-controller="DateController">
<label class="item-input"> <span class="input-label">Start</span>
<input type="date" data-ng-model="startDate" ng-change="setStart(startDate)" required validatedateformat calendar>
</label>
<label class="item-input"> <span class="input-label">End</span>
<input type="date" data-ng-model="endDate" ng-change="setEnd(endDate)" required validatedateformat calendar>
</label>
<button button="button" ng-disabled="planningForm.$invalid" ng-click="load()" class="button button-positive">
Run
</button>
</div <label class="item-input"> <span class="input-label">Start</span>
<input type="date" data-ng-model="startDate" ng-change="setStart(startDate)" required validatedateformat calendar>
</label>
<label class="item-input"> <span class="input-label">End</span>
<input type="date" data-ng-model="endDate" ng-change="setEnd(endDate)" required validatedateformat calendar>
</label>
Vérifiez cette directive entièrement fonctionnelle pour MEAN.JS (Angular.js, bootstrap, Express.js et MongoDb)
Basé sur la réponse de @Blackhole, nous venons de le finir pour l’utiliser avec mongodb et express.
Il vous permettra de sauvegarder et de charger des dates à partir d'un connecteur de mangouste
J'espère que ça aide!!
angular.module('myApp')
.directive(
'dateInput',
function(dateFilter) {
return {
require: 'ngModel',
template: '<input type="date" class="form-control"></input>',
replace: true,
link: function(scope, Elm, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.unshift(function (modelValue) {
return dateFilter(modelValue, 'yyyy-MM-dd');
});
ngModelCtrl.$parsers.Push(function(modelValue){
return angular.toJson(modelValue,true)
.substring(1,angular.toJson(modelValue).length-1);
})
}
};
});
Le JADE/HTML:
div(date-input, ng-model="modelDate")
Si vous utilisez Angular Material Design, vous pouvez utiliser le composant datepicker et cela fonctionnera sous Firefox, IE, etc.
https://material.angularjs.org/latest/demo/datepicker
Avertissement juste, l'expérience personnelle montre qu'il y a des problèmes avec cela, et apparemment, cela est en train d'être retravaillé à l'heure actuelle. Vois ici: