J'ai une connexion mongoose à une base de données contenant des objets Date dans une collection. Je souhaite afficher ces objets Date à l'aide du contrôle DatePicker
de Angular Material. L'objet Date suit le format de chaîne ISO.
Voici un extrait de code:
<md-datepicker
ng-model="license.expirationdate" md-placeholder="Enter date">
</md-datepicker>
Je reçois l'erreur suivante:
Le ng-model
pour md-datepicker
doit être une instance de date.
Lors de mes recherches, j'ai découvert que vous pouviez utiliser des filtres pour créer une instance de date, mais cela ne fonctionnait pas pour moi.> J'ai reçu un message d'erreur indiquant que la valeur du modèle ne peut pas être assignée lors de l'utilisation de filtres simples. Le filtre a simplement renvoyé un nouvel objet Date basé sur la chaîne entrée.
Comment puis-je formater les chaînes en objets Date tout en permettant les changements ng-model
?
EDIT: schéma pour mongoose Var Schema = mongoose.Schema;
var Schema = mongoose.Schema;
var modelschema = new Schema({
name : String,
licensetype : String,
activationcount : Number,
expirationdate: Date,
key : String
})
voici le routage express qui remplit le schéma
app.post('/licenses', function (req, res) {
console.log(req.body.expirationDate);
License.create({
name: req.body.licenseName,
licensetype: req.body.licenseType,
activationcount: 0,
expirationdate: req.body.expirationDate,
key: "123456"
}, function (err, license) {
if (err) {
res.send(err);
console.log(err);
}
//Send user back to main page
res.writeHead(301, {
'Location': '/',
'Content-Type': 'text/plain'
});
res.end();
}
)
});
Voici un exemple:
Balisage:
<div ng-controller="MyCtrl">
<md-datepicker ng-model="dt" md-placeholder="Enter date" ng-change="license.expirationdate = dt.toISOString()">
</md-datepicker>
{{license.expirationdate}}
</div>
JavaScript:
app.controller('MyCtrl', function($scope) {
$scope.license = {
expirationdate: '2015-12-15T23:00:00.000Z'
};
$scope.dt = new Date($scope.license.expirationdate);
});
Fiddle: http://jsfiddle.net/masa671/jm6y12un/
METTRE À JOUR:
Avec ng-repeat
:
Balisage:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-model="dataMod[$index].dt"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = dataMod[$index].dt.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
JavaScript:
app.controller('MyCtrl', function($scope) {
var i;
$scope.data = [
{ license:
{ expirationdate: '2015-12-15T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-20T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-25T23:00:00.000Z' }
}
];
$scope.dataMod = [];
for (i = 0; i < $scope.data.length; i += 1) {
$scope.dataMod.Push({
dt: new Date($scope.data[i].license.expirationdate)
});
}
});
Vous pouvez utiliser ng-init, un filtre personnalisé et ng-change et accomplir cela dans le balisage.
JavaScript:
app.filter('toDate', function() {
return function(input) {
return new Date(input);
}
})
HTML:
<md-datepicker
ng-init="date = (license.expirationdate | toDate)"
ng-model="date"
ng-change="license.expirationdate = date.toISOString()"
md-placeholder="Enter date">
</md-datepicker>
Avec cette approche, vous n'avez pas besoin d'encombrer votre code de contrôleur avec la logique View. L'inconvénient est que toute modification apportée par programme à license.expirationdate dans le contrôleur ne sera pas automatiquement reflétée dans la vue.
http://jsfiddle.net/katfby9L/1/
// Configure the $httpProvider by adding our date transformer
app.config(["$httpProvider", function ($httpProvider) {
$httpProvider.defaults.transformResponse.Push(function(responseData){
convertDateStringsToDates(responseData);
return responseData;
});
}]);
var regexIso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
function convertDateStringsToDates(input) {
// Ignore things that aren't objects.
if (typeof input !== "object") return input;
for (var key in input) {
if (!input.hasOwnProperty(key)) continue;
var value = input[key];
var match;
// Check for string properties which look like dates.
// TODO: Improve this regex to better match ISO 8601 date strings.
if (typeof value === "string" && (match = value.match(regexIso8601))) {
// Assume that Date.parse can parse ISO 8601 strings, or has been shimmed in older browsers to do so.
var milliseconds = Date.parse(match[0]);
if (!isNaN(milliseconds)) {
input[key] = new Date(milliseconds);
}
} else if (typeof value === "object") {
// Recurse into object
convertDateStringsToDates(value);
}
}
}
Cela convertira automatiquement toutes les chaînes dans les réponses JSON du serveur à ce jour.
Je le ferais comme ça:
Html:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-init="date = StrToDate(d.license.expirationdate);"
ng-model="date"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = date.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
Dans votre contrôleur
$scope.StrToDate = function (str) {
return new Date(str);
}
Je devais faire une date par défaut de 6 mois à compter du jour en cours ...
Après de longues expériences de conversion de date au format ISO et retour, j'ai créé une solution simple que je n'ai pas trouvée ici.
L'idée générale: prenez le temps aujourd'hui et ajoutez/soustrayez le temps en millisecondes jusqu'à la date souhaitée.
html:
<div flex-gt-xs>
<h4 class="md-title">Date From:</h4>
<md-datepicker ng-model="vm.sixMonthBeforeNow" md-placeholder="Date From:"></md-datepicker>
{{vm.sixMonthBeforeNow}}
</div>
manette:
vm.sixMonthBeforeNow = new Date((+new Date) - 15778800000); // today - 6 month in ISO format (native for Angular Material Datepicker)
Peut-être que ce sera utile pour quelqu'un ...
J'ai créé une directive personnalisée pour gérer cela pour moi. J'ai utilisé la classe Date de Sugarjs.com pour que cela fonctionne comme je l'ai implémenté. Cette méthode garantit que la date est toujours affichée comme une date et ne saute pas lorsque l'offset UTC est impliqué. Vous pouvez changer le formateur en return new Date(input)
si vous ne voulez pas vous limiter à UTC.
angular.module 'app.components'
.directive 'autoChangeStringDates', ->
directive =
restrict: 'A'
require: 'ngModel'
priority: 2000
link: (scope, el, attrs, ngModelController) ->
ngModelController.$formatters.Push((input) ->
if typeof input == Date
return input
else
return Date.create(input, {fromUTC: true})
)
return
Vous l'utilisez ensuite dans votre balise HTML comme si
<md-datepicker ng-model='myModel' auto-change-string-dates></md-datepicker>