2015-11-10 11 views
6

używam kątowa Bootstrap UI DatePicker: https://angular-ui.github.io/bootstrap/#/datepickerParse datę ciąg do obiektu Date podczas ładowania kątowa Bootstrap UI Datepicker

Kiedy renderowanie formularza za pomocą danych otrzymanych z serwera, nie ma problemu z pola datetime. Moja datepicker wejściowe wygląda następująco:

<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> 

mój serwer zwraca datetime odpowiedzi jako JSON wyrażenie:

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

Kiedy przypisać danych odpowiedzi do modelu $scope.item = response;, datepicker pola wejściowe są wyświetlane poprawnie (poprawna data jest wybrane i jest poprawnie sformatowane w wybranym formacie). Problem polega na tym, że walidacja nie przechodzi. I otrzymujemy:

itemForm.startedAt.$invalid == true 

zauważyłem, że dane związane z polem datepicker powinny być Date przedmiot i nie string (kiedy wybrać nową datę z datepicker, $scope.item.startedAt jest Date)

udało mi się obejść ten problem i to zrobić w kontrolerze:

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

to działa w ten sposób ... Ale nie chciałbym, aby ręcznie przekonwertować ciąg datę zrobić za każdym razem dostaję odpowiedzi z serwera. Starałem się stworzyć dyrektywę, które można przypisać do pola datepicker więc konwertuje ng-model dla mnie:

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

to działa, bo teraz widzę Date przedmiot, kiedy modelu wyjście moim zdaniem : {{item.startedAt}}. Jednak wciąż nie można sprawdzić poprawności ! Podejrzewam, że jest to problem ze zrozumieniem, w jaki sposób dane przepływają między modelem a widokiem, oraz jak działa Bootstrap w interfejsie użytkownika.

Również kiedy mogę zmienić dyrektywę z $formatters.push do $formatters.unshift, walidacja działa OK, ale datepicker nie sformatować datetime (insted ładnie formattet yyyy-MM-dd widzę ciąg ISO wewnątrz wejście)

+1

AWW człowieka jesteśmy o dokładnie ten sam problem tutaj !!! –

+0

@VictorParmar obecnie robię to na odwrót - konwertowanie łańcucha odpowiedzi na obiekt Date podczas odbierania z serwera. I konwertowanie obiektu Date na ciąg znaków podczas wysyłania na serwer. Wszystko to odbywa się ręcznie w regulatorze kątowym. Może po prostu wydobędę tę logikę jako usługę Angular, ale nie sądzę, że można to zrobić za pomocą dyrektywy – rsobon

+2

tak, przyłącz się do klubu - skończyło się na zrobieniu tego samego :) –

Odpowiedz

1

Jak to jest zamierzone Zachowanie datepicker typu kątowego-ui-bootstrap (https://github.com/angular-ui/bootstrap/issues/4690), w końcu skorzystałem z biblioteki Angular service/factory i biblioteki moment.

Usługa dateConverter może być wstrzykiwana globalnie w celu przechwycenia wszystkich żądań/odpowiedzi HTTP lub tylko w żądanych kontrolerach.

Używam tutaj Restangular bibliotekę do obsługi żądania REST API, stąd metodę response.plain() który trwa tylko właściwości obiektów, a nie Restangular metody/właściwości.

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

Ten wybuchł jak kątowych. UI.Bootstrap v0.13.2 (8-2-2015) Obniżenie do wersji 0.13.1 działa, w którym utknąłem dzisiaj.

Wesleycho mówi, że to było zrobione celowo https://github.com/angular-ui/bootstrap/issues/4690

Jestem gotowy na inny termin zbieraczy obsługujących ciągi jeśli ktoś ma sugestię

... wkrótce po wysłaniu tego Zeszłam non-kątowe ścieżka, z której nie jestem dumny, ale działa zarówno w typie HTML5 = "date", jak i uib-datepicker-popup. Mam wyrażenie regularne, które określa, czy ciąg przypomina jeden z dwóch formatów datalizowanych widziałem, a następnie mam rekursywną funkcję javascript do przechodzenia przez drzewo json i zastąpić te ciągi Date(). Nazwałbyś to tuż przed umieszczeniem $ scope (lub viewmodel) ...

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

(nie muszę sprawdzić długość ciągów, ale pomyślałem, że to oszczędzić kilka cykli procesora przez nie uruchamiając regex jeśli ciąg nie jest oczywiście data)

//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

kiedy używasz pętli for javascript javascript powinien również użyć hasOwnProperty() – rsobon

0

można przekształcić ciąg do tej pory w restangular transformatora, coś w tym

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