2017-02-15 70 views
6

Mam dynamicznie generowane Angular 2 FormGroup z wieloma polami wejściowymi FormControl. Niektóre z wejść to Daty, które są pobierane z serwera jako znaczniki czasu unix.Angular 2 data pipe wewnątrz Input FormControl

Co chciałbym zrobić, to:

  1. , aby móc przetłumaczyć uniksowego znacznika czasu do postaci czytelnej dla człowieka, kiedy mój FormGroup jest wypełniona, a także
  2. tłumaczyć ludzką reprezentację data do znacznika czasu unixa po przesłaniu formularza .

Część 1 jest dość proste, używając dat rury kątowej jest tak:

<input class="form-control" [formControlName]="question.key" 
[value]="this.form.controls[this.question.key].value | date:'dd/MM/yyyy'"> 

Gdzie this.form jest odniesienie do FormGroup i this.question jest niestandardowej klasy otoki na podstawie oficjalnego tutoriala o dynamiczne formularze:

https://angular.io/docs/ts/latest/cookbook/dynamic-form.html

Próbując zmienić datę wejścia w ten sposób nie zadziała, ponieważ rura będzie stale starają się przekształcić wartość wejściową, a tym samym sprawiają, że dane wejściowe nie nadają się do użycia, jeśli nie wyrzucą niepoprawnego argumentu dla wyjątku "DatePipe" dla potoku.

Aby wyjaśnić, wypełnij mój formularz za pomocą api FormGroup.patchValue() i prześlij dane formularza za pomocą api FormGroup.getRawValue().

Próbowałem użyć elementu wyboru selektora daty Angular 2, ale moje duże formularze były dość powolne, więc chciałbym zrobić to bez niestandardowych zbieraczy dat lub dowolnych widgetów zależnych od jQuery.

Z góry dziękuję.

Odpowiedz

7

Jednym ze sposobów, aby zrobić coś takiego byłoby utworzyć komponent za wkład, który implementuje ControlValueAccessor

pomostem między kontrolą i native elementu.

A ControlValueAccessor generuje operacje zapisu nowej wartości na element DOM reprezentujący kontrolkę wejściową.

Aby uzyskać więcej informacji, zobacz numer DefaultValueAccessor.

Coś jak to powinno załatwić sprawę (nie sprawdzone)

export const DATE_VALUE_ACCESSOR: any = { 
    provide: NG_VALUE_ACCESSOR, 
    useExisting: forwardRef(() => MyDateInput), 
    multi: true 
}; 

@Component({ 
    template:`<input #input (input)="onChange($event)" (blur)="touchCallback()" type="date" [attr.disabled]="disabled?true:null">` 
    selector:"my-input", 
    styles:[], 
    providers:[DATE_VALUE_ACCESSOR] 
}) 
export class MyDateInput implements ControlValueAccessor{ 
    @ViewChild("input") 
    input:ElementRef; 
    disabled=false; 
    changeCallback=(data:any)=>{}; 
    touchCallback=()=>{}; 

    onChange(event){ 
     let timestamp=this.convertToTimestamp(event.target.value); 
     this.changeCallback(timestamp); 
    } 

    convertToTimestamp(formatedDate){ 
     //TODO:implement 
    } 

    convertFromTimestamp(timestamp){ 
     //TODO:implement 
    } 

    writeValue(obj: any){ 
     let formatedDate=this.convertFromTimestamp(obj); 
     this.input.nativeElement.value=formatedDate; 
    } 

    registerOnChange(fn: any){ 
     this.changeCallback=fn; 
    } 

    registerOnTouched(fn: any){ 
     this.touchCallback=fn; 
    } 

    setDisabledState(isDisabled: boolean){ 
     this.disabled=isDisabled; 
    } 
} 

to powinieneś być w stanie używać go tak:

<my-input class="form-control" [formControlName]="question.key"></my-input> 

lub

<my-input [(ngModel)]="myModel"></my-input> 
+0

Dzięki, spróbuję tego podejścia i wrócę do Ciebie tak szybko, jak to możliwe. – ktsangop

+0

Ups, właśnie zdałem sobie sprawę, że zapomniałem ważną rolę w deklaracji "@ Component". Będę edytować jak najszybciej. – n00dl3

+0

changeCallback i touchCallback muszą zostać zainicjalizowane i przypuszczam, że tak jak "touchCallback: any =() => {};' Poza tym i po wielu lekturze, myślę, że rozumiem jak to działa teraz! Przyjmę wkrótce twoją odpowiedź, jeśli nie mam innych pytań. Dzięki! – ktsangop