6

Ich verwende Angular UI Bootstrap Datumsauswahl: https://angular-ui.github.io/bootstrap/#/datepickerParse Datums-String-Objekt Datum beim Laden Angular UI Bootstrap Datepicker

Wenn ich machen Form unter Verwendung von Daten vom Server empfangen, ist es ein Problem mit Datetime-Felder. Mein Eingangsdatepicker sieht wie folgt aus:

<form name="itemForm"> 
    <input type="datetime" class="form-control" id="startedAt" name="startedAt" 
      ng-model="item.startedAt" 
      ng-click="open($event, 'startedAt')" 
      uib-datepicker-popup="yyyy-MM-dd" 
      is-open="datepickers.startedAt" 
    /> 
</form> 

Mein Server gibt Antwort Datetime als JSON-String:

{  
    ... 
    startedAt: "2015-05-29T02:00:00+0200" 
} 

Wenn ich Antwortdaten an das Modell $scope.item = response; zuweisen, wird picker Eingabefeld korrekt wiedergegeben (richtige Datum ist ausgewählt und es ist korrekt in dem Format formatiert, das ich ausgewählt habe). Das Problem besteht darin, dass die Validierung nicht bestanden wird. Ich bekomme:

itemForm.startedAt.$invalid == true 

Ich bemerkte, dass an den Datepicker Feld gebunden Daten Date Objekt sein sollte und nicht die Zeichenfolge (wenn ich neue Datum von der Datumsauswahl wählen, $scope.item.startedAt ist ein Date)

ich es geschafft, zu arbeiten, um dieses Problem und tut dies in der Steuerung:

$scope.item = response; 
$scope.item.startedAt = new Date($scope.item.startedAt); 

es so funktioniert ... Aber ich mag nicht manuell jedes Mal, wenn ich eine Antwort vom Server-String tut Datum konvertieren bekommen. Ich habe versucht, eine Richtlinie zu erstellen, dass ich mit dem Datepicker Eingabefeld zuweisen, damit es die ng-model für mich konvertiert:

.directive("asDate", function() { 
    return { 
     require: 'ngModel', 
     link: function (scope, element, attrs, modelCtrl) { 

      modelCtrl.$formatters.push(function (input) { 

       var transformedInput = new Date(input); 

       if (transformedInput != input) { 
        modelCtrl.$setViewValue(transformedInput); 
        modelCtrl.$render(); 
       } 

       return transformedInput; 
      }); 
     } 
    } 
}) 

Nun, es funktioniert, denn jetzt kann ich Date Objekt sehen, wenn ich Output-Modell aus meiner Sicht : {{item.startedAt}}. Aber immer noch Validierung schlägt fehl! Ich vermute, das ist ein Problem mit mir zu verstehen, wie Daten zwischen Modell und der Ansicht fließen und wie UI Bootstrap in es einhakt.

Auch wenn ich meine Richtlinie $formatters.unshift von $formatters.push wechseln, kann die Validierung in Ordnung, aber picker nicht formatiert meine Datetime (insted von schön formattet yyyy-MM-dd sehe ich ISO-String innerhalb des Eingangs)

+1

AWW Mann haben wir genau das gleiche Problem hier verwandeln kann !!! –

+0

@VictorParmar derzeit mache ich das den Weg herum - Umwandlung der Antwort-String in Date-Objekt beim Empfang vom Server. Und Konvertieren von Date-Objekt in Zeichenfolge beim Senden an den Server. All dies erfolgt im Angular Controller manuell. Vielleicht werde ich nur diese Logik als Angular Service extrahieren, aber ich denke nicht, dass es möglich ist, mit Richtlinie zu tun – rsobon

+2

ja dem Club beizutreten - wir am Ende tun die gleiche Sache :) –

Antwort

1

Da dies beabsichtigt ist Verhalten von Angular-Ui-Bootstrap-Datepicker (https://github.com/angular-ui/bootstrap/issues/4690), endete ich mit Angular Service/Factory und moment Bibliothek.

Der Dienst dateConverter kann global injiziert werden, um alle HTTP-Requests/-Antworten abzufangen oder nur in den gewünschten Controllern.

Hier verwende ich Restangular Bibliothek, um Anfrage an REST API zu behandeln, daher die response.plain() Methode, die nur Objekteigenschaften und nicht Restangular Methoden/Eigenschaften.

var Services = angular.module('app.Services', []); 

Services 
    .factory('dateConverter', ['dateFilter', function (dateFilter) { 

     var dateConverter = {}; 

     dateConverter.prepareResponse = function (response) { 
      for(prop in response.plain()) { 
       if (response.hasOwnProperty(prop)) { 
        if(moment(response[prop], moment.ISO_8601, true).isValid()) { 
         response[prop] = new Date(response[prop]); 
        } 
       } 
      } 
      return response; 
     }; 

     dateConverter.prepareRequest = function (item) { 
      for(prop in item.plain()) { 
       if (item.hasOwnProperty(prop)) { 
        if(angular.isDate(item[prop])){ 
         item[prop] = dateFilter(item[prop] , "yyyy-MM-ddTHH:mm:ssZ") 
        } 
       } 
      } 
      return item; 
     }; 

     return dateConverter; 
    }]) 
; 
0

Dies als von Angular brach. UI.Bootstrap v0.13.2 (8-2-2015) Downgrade auf 0.13.1 funktioniert, wo ich heute feststecke.

Wesleycho sagt dies absichtlich https://github.com/angular-ui/bootstrap/issues/4690

bereit Ich bin für andere Datumsauswahl, die Strings unterstützen getan wurde, wenn jemand einen Vorschlag

hat ... bald nach diesem Posting ich ein nicht-Winkel ging Pfad, auf den ich nicht stolz bin, aber es funktioniert sowohl für HTML5 type = "date" als auch für uib-datepicker-popup. Ich habe einen regulären Ausdruck, der bestimmt, ob eine Zeichenfolge einem der beiden serialisierten Datumsformate ähnelt, die ich gesehen habe, und dann habe ich eine rekursive JavaScript-Funktion, um eine JSON-Struktur zu durchlaufen und diese Zeichenfolgen durch Date() zu ersetzen. Du würdest es nennen, bevor du $ scope (oder viewmodel) eingibst ...

$http.get("../api/comm/" + commId 
    ).success(function (resp) { 
     fixDates(resp); 
     vm.comm = resp; 
    }); 

(ich überprüfen müssen nicht die String-Länge, aber ich dachte, es würde durch nicht läuft die Regex einige CPU-Zyklen ersparen, wenn die Zeichenfolge offensichtlich kein Datum ist)

//2015-10-01T00:00:00-04:00 
//2015-11-20T18:15:56.6229516-05:00 
var isDate = new RegExp("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{7})?-\\d{2}:00"); 

function fixDates(json) { 
    for (i in json) 
     if (typeof (json[i]) == "object") 
      fixDates(json[i]); 
     else if (typeof (json[i]) == "string" && (json[i].length == 25 || json[i].length == 33) && isDate.test(json[i])) 
      json[i] = new Date(json[i]); 
}; 
+0

wenn Sie Javascript for-in-Schleife Sie wahrscheinlich verwenden sollte auch hasOwnProperty() verwenden – rsobon

0

Sie String to Date in restangular Transformator, so etwas wie dieses

RestangularConfigurer 
    .addElementTransformer('<RESTRESOURCENAME>', false, function (element) { 
     element.createDate = new Date(element.createDate); 
     return element; 
    })