Wie formatiere ich ein Datum mit ng-model?


93

Ich habe eine Eingabe definiert als

<input class="datepicker" type="text" ng-model="clientForm.birthDate" />

Welches ist manipuliert, um an anderer Stelle auf der Seite angezeigt zu werden:

<tr>
    <th>Birth Date</th>
    <td>{{client.birthDate|date:'mediumDate'}}</td>
</tr>

Wenn die Seite geladen wird, wird das Geburtsdatum so gut wie formatiert Dec 22, 2009. Wenn ich jedoch in mein Bild schaue <input>, wird angezeigt, Tue Dec 22 2009 00:00:00 GMT-0800 (Pacific Standard Time)wie JS DateObjekte als Zeichenfolgen rendert .

Erstens, wie kann ich Angular anweisen, das Datum in <input>so etwas wie anzuzeigen 12/22/2009? Ich kann mich nicht |filtersinnerhalb des ng-modelAttributs bewerben .

Zweitens <td>scheint mein anderer Text (innerhalb des ) den |dateFilter nicht mehr anzuwenden , sobald ich das Datum bearbeite und es sogar im Originalformat behalte. Es ändert plötzlich das Format, um es an das Eingabetextfeld anzupassen. Wie kann ich den |dateFilter bei jedem Modellwechsel anwenden ?


Verwandte Fragen:


Ich hatte auch ein Problem damit, kam aber mit einer einfacheren Lösung unter Verwendung von Standard-js- Date()Funktionen: $scope.departDate = new Date(); $scope.departTime = $scope.departDate.toTimeString().slice(0, 5);Und keine Notwendigkeit für andere Filter oder knifflige Problemumgehungen in AngularJS IMO.
Boldnik

Antworten:


71

Verwenden Sie die benutzerdefinierte Validierung von Formularen http://docs.angularjs.org/guide/forms Demo: http://plnkr.co/edit/NzeauIDVHlgeb6qF75hX?p=preview

Direktive mit Formatierern und Parsern und MomentJS )

angModule.directive('moDateInput', function ($window) {
    return {
        require:'^ngModel',
        restrict:'A',
        link:function (scope, elm, attrs, ctrl) {
            var moment = $window.moment;
            var dateFormat = attrs.moDateInput;
            attrs.$observe('moDateInput', function (newValue) {
                if (dateFormat == newValue || !ctrl.$modelValue) return;
                dateFormat = newValue;
                ctrl.$modelValue = new Date(ctrl.$setViewValue);
            });

            ctrl.$formatters.unshift(function (modelValue) {
                if (!dateFormat || !modelValue) return "";
                var retVal = moment(modelValue).format(dateFormat);
                return retVal;
            });

            ctrl.$parsers.unshift(function (viewValue) {
                var date = moment(viewValue, dateFormat);
                return (date && date.isValid() && date.year() > 1950 ) ? date.toDate() : "";
            });
        }
    };
});

4
Ich wollte ein kleines Beispiel für Formatierer und Parser erstellen. Dank Ihrer heutigen Frage habe ich den Grund dafür bekommen.
SunnyShah

1
@ Mark, das Nan-Problem in der zweiten Geige wurde behoben. ;)
SunnyShah

1
Zweiter Ansatz entfernt. Es war viel zu fehlerhaft.
SunnyShah

1
Sie können die On-Change-Direktive verwenden, um weitere Verbesserungen vorzunehmen. stackoverflow.com/questions/14477904/…
SunnyShah

7
@ SunnyShah - tolles Zeug, sehr hilfreich, vielen Dank. Ich habe mich gefragt, warum Sie haben var dateFormat = attrs.moMediumDate;und nicht var dateFormat = attrs.moDateInput;moMediumDate scheint nirgendwo festgelegt zu sein. Wenn die Eingaben nicht dynamisch erstellt werden, wird niemals ein Anfangsformat ausgewählt.
Toxaq

37

Hier ist eine sehr praktische Direktive Winkel-Datum / Uhrzeit . Sie können es so verwenden:

<input type="text" datetime="yyyy-MM-dd HH:mm:ss" ng-model="myDate">

Außerdem wird Ihrer Eingabe eine Maske hinzugefügt und eine Validierung durchgeführt.


1
Ich habe diese Richtlinie auch verwendet, danke. Wenn Sie es mit dem jQuery UI Datepicker verwenden, müssen Sie sicherstellen, dass das im datetime="<format>"Attributwert angegebene Format mit dem in der dateFormatOption Datepicker angegebenen Format übereinstimmt .
Tylerwal

1
Ich frage mich, wie es möglich ist, dass es hier eine perfekte Lösung mit nur wenigen Stimmen gibt. Soviel zu Daten, und Sie können sie genau hier, genau jetzt, lösen! Danke Alter.
C0ZEN

2
Ich bin sicher, dass mehr Leute darüber abstimmen würden, wenn die Dokumentation verbessert würde, um die Aufnahme in eine vorhandene Winkel-App zu vereinfachen.
Joel Hansen

8

Ich habe eine einfache Anweisung erstellt, damit Standardformularelemente input[type="date"]mit AngularJS ~ 1.2.16 ordnungsgemäß funktionieren.

Schauen Sie hier: https://github.com/betsol/angular-input-date

Und hier ist die Demo: http://jsfiddle.net/F2LcY/1/


Hey @Lorenzo, was meinst du? Könnten Sie bitte näher darauf eingehen?
Slava Fomin II

Der Monat Jahr Tag sind in Französisch wie Lun Mar Mer für Mo Di, Wen
Merlin

@ Lorenzo Ich bin nicht sicher, ob ich es nicht verstehe. Die Richtlinie hat nichts mit Lokalisierung zu tun. Wahrscheinlich übernimmt die von Ihnen verwendete Formatierungsfunktion die Gebietsschemaeinstellung von Ihrem Browser / System. Wenn Sie ein Beispiel angeben, kann ich Ihnen helfen (jsfiddle).
Slava Fomin II

1
unterstütze nur Chrom, so schlecht.
GeminiYellow

Ziel der Richtlinie ist es, alle Plattformen zu unterstützen. Wenn Sie Probleme damit haben, warum erstellen Sie kein Problem mit GitHub Repo? Ich antworte immer auf alle Fragen.
Slava Fomin II

7

Ich verwende jquery datepicker, um das Datum auszuwählen. Meine Direktive liest das Datum und konvertiert es in das json-Datumsformat (in Millisekunden), speichert es in ng-modelDaten, während das formatierte Datum angezeigt wird.

HTML Quelltext:

<input type="text" jqdatepicker  ng-model="course.launchDate" required readonly />

Winkelrichtlinie:

myModule.directive('jqdatepicker', function ($filter) {
    return {
        restrict: 'A',
        require: 'ngModel',
         link: function (scope, element, attrs, ngModelCtrl) {
            element.datepicker({
                dateFormat: 'dd/mm/yy',
                onSelect: function (date) {   
                    var ar=date.split("/");
                    date=new Date(ar[2]+"-"+ar[1]+"-"+ar[0]);
                    ngModelCtrl.$setViewValue(date.getTime());            
                    scope.$apply();
                }
            });
            ngModelCtrl.$formatters.unshift(function(v) {
            return $filter('date')(v,'dd/MM/yyyy'); 
            });

        }
    };
});

Oh mein Gott!! Vielen Dank !! Ich habe buchstäblich zwei Tage nach so etwas wie dieser Antwort gesucht, aber keine gefunden! Du rockst!
Michael Rentmeister

Fantastisch. Ich habe eine Weile nach so etwas gesucht. Ich verwende materializecss für meine Lösung. Wenn jemand stubles auf diesem und Anforderungen diese Richtlinie für materialisieren konvertieren, tauscht einfach aus element.datepickermitelement.pickadate
IWI

7

Da Sie Datepicker als Klasse verwendet haben, gehe ich davon aus, dass Sie einen Jquery-Datepicker oder ähnliches verwenden.

Es gibt eine Möglichkeit, das zu tun, was Sie beabsichtigen, ohne moment.js zu verwenden, indem Sie nur die Direktiven datepicker und anglejs verwenden.

Ich habe hier in dieser Geige ein Beispiel gegeben

Auszüge aus der Geige hier:

  1. Datepicker hat ein anderes Format und AngularJS-Format ist unterschiedlich. Sie müssen die entsprechende Übereinstimmung finden, damit das Datum im Steuerelement vorausgewählt und auch im Eingabefeld ausgefüllt wird, während das ng-Modell gebunden ist. Das folgende Format entspricht dem 'mediumDate'Format von AngularJS.

    $(element).find(".datepicker")
              .datepicker({
                 dateFormat: 'M d, yy'
              }); 
    
  2. Die Datumseingabeanweisung muss eine vorläufige Zeichenfolgenvariable enthalten, um die vom Menschen lesbare Datumsform darzustellen.

  3. Das Aktualisieren über verschiedene Seitenabschnitte sollte über Ereignisse wie $broadcastund erfolgen $on.

  4. Die Verwendung eines Filters zur Darstellung des Datums in lesbarer Form ist auch im ng-Modell möglich, jedoch mit einer temporären Modellvariablen.

    $scope.dateValString = $filter('date')($scope.dateVal, 'mediumDate');

6

Ich verwende die folgende Anweisung, die mich und die meisten Benutzer sehr glücklich macht! Es verwendet Moment zum Parsen und Formatieren. Es sieht ein bisschen aus wie das von SunnyShah, das bereits erwähnt wurde.

angular.module('app.directives')

.directive('appDatetime', function ($window) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var moment = $window.moment;

            ngModel.$formatters.push(formatter);
            ngModel.$parsers.push(parser);

            element.on('change', function (e) {
                var element = e.target;
                element.value = formatter(ngModel.$modelValue);
            });

            function parser(value) {
                var m = moment(value);
                var valid = m.isValid();
                ngModel.$setValidity('datetime', valid);
                if (valid) return m.valueOf();
                else return value;
            }

            function formatter(value) {
                var m = moment(value);
                var valid = m.isValid();
                if (valid) return m.format("LLLL");
                else return value;

            }

        } //link
    };

}); //appDatetime

In meiner Form benutze ich es so:

<label>begin: <input type="text" ng-model="doc.begin" app-datetime required /></label>
<label>end: <input type="text" ng-model="doc.end" app-datetime required /></label>

Dadurch wird ein Zeitstempel (Millisekunden seit 1970) an doc.beginund gebunden doc.end.


1
Es ist leicht zu übersehen, dass sich innerhalb dieser Verknüpfungsfunktion ngModelIhre benutzerdefinierte Kennung für das Controller-Argument befindet und kein direkter, benannter Verweis auf ngModel. Dies ist ein Punkt, an dem die Konvention, dieses Argument als "Strg" oder "Controller" zu bezeichnen, die Dinge klarer hält und Verwirrung vermeidet.
XML

Vielen Dank! Ich habe den ganzen Tag nach einem guten Weg gesucht, dies zu tun. Leider umfassten die meisten anderen Korrekturen den Wechsel zu einem speziell für Angular geschriebenen Datepicker, und das war zu viel Arbeit.
Josh Mouch

Ich habe sowohl deine als auch die Antwort von @SunnyShah ausprobiert, aber seine schien nicht zu funktionieren. Nicht sicher warum.
Josh Mouch

3

In Angular2 + für alle Interessierten:

<input type="text" placeholder="My Date" [ngModel]="myDate | date: 'longDate'">

mit Filtertyp in DatePipe Angular.


Dang, ich stecke in AngularJS fest, an dem ich arbeiten musste, und ich hasse es! Ich wünschte, ich hätte das oben genannte, mit dem ich arbeiten könnte.
Jordanien

2

Ich möchte, dass der Server das Datum ohne Änderung zurückgibt und Javascript die Ansicht massiert. Meine API gibt "MM / TT / JJJJ hh: mm: ss" von SQL Server zurück.

Ressource

angular.module('myApp').factory('myResource',
    function($resource) {
        return $resource('api/myRestEndpoint/', null,
        {
            'GET': { method: 'GET' },
            'QUERY': { method: 'GET', isArray: true },
            'POST': { method: 'POST' },
            'PUT': { method: 'PUT' },
            'DELETE': { method: 'DELETE' }
        });
    }
);

Regler

var getHttpJson = function () {
    return myResource.GET().$promise.then(
        function (response) {

            if (response.myDateExample) {
                response.myDateExample = $filter('date')(new Date(response.myDateExample), 'M/d/yyyy');
            };

            $scope.myModel= response;
        },
        function (response) {
            console.log(response.data);
        }
    );
};

myDate-Validierungsrichtlinie

angular.module('myApp').directive('myDate',
    function($window) {
        return {
            require: 'ngModel',
            link: function(scope, element, attrs, ngModel) {

                var moment = $window.moment;

                var acceptableFormats = ['M/D/YYYY', 'M-D-YYYY'];

                function isDate(value) {

                    var m = moment(value, acceptableFormats, true);

                    var isValid = m.isValid();

                    //console.log(value);
                    //console.log(isValid);

                    return isValid;

                };

                ngModel.$parsers.push(function(value) {

                    if (!value || value.length === 0) {
                         return value;
                    };

                    if (isDate(value)) {
                        ngModel.$setValidity('myDate', true);
                    } else {
                        ngModel.$setValidity('myDate', false);
                    }

                    return value;

                });

            }
        }
    }
);

HTML

<div class="form-group">
    <label for="myDateExample">My Date Example</label>
    <input id="myDateExample"
           name="myDateExample"
           class="form-control"
           required=""
           my-date
           maxlength="50"
           ng-model="myModel.myDateExample"
           type="text" />
    <div ng-messages="myForm.myDateExample.$error" ng-if="myForm.$submitted || myForm.myDateExample.$touched" class="errors">
        <div ng-messages-include="template/validation/messages.html"></div>
    </div>
</div>

template / validation / messages.html

<div ng-message="required">Required Field</div>
<div ng-message="number">Must be a number</div>
<div ng-message="email">Must be a valid email address</div>
<div ng-message="minlength">The data entered is too short</div>
<div ng-message="maxlength">The data entered is too long</div>
<div ng-message="myDate">Must be a valid date</div>

1

Angularjs UI-Bootstrap Sie können AngularJs UI-Bootstrap verwenden. Es bietet auch eine Datumsüberprüfung

<input type="text"  class="form-control" 
datepicker-popup="{{format}}" ng-model="dt" is-open="opened" 
min-date="minDate" max-date="'2015-06-22'"  datepickeroptions="dateOptions"
date-disabled="disabled(date, mode)" ng-required="true"> 



In der Steuerung können Sie festlegen, in welchem ​​Format das Datum als Datumsfilter angezeigt werden soll.

$ scope.formats = ['TT-MMMM-JJJJ', 'JJJJ / MM / TT', 'TT.MM.JJJJ', 'Kurzdatum'];


Sie müssen keine Direktive nur für ein einzelnes Eingabefeld implementieren
P.JAYASRI
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.