web-dev-qa-db-fra.com

Comment formater la chaîne ng-model en date pour datepicker matériel

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

});
14
WJM

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

Fiddle: http://jsfiddle.net/masa671/bmqpyu8g/

16
masa

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.

9
Jeffrey Patterson

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.

8
Toolkit

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

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)

résultat:  enter image description here

Peut-être que ce sera utile pour quelqu'un ...

1
Igor Arkhipenko

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>
0
Tyrone Wilson