web-dev-qa-db-fra.com

Angular 2 pipe de date à l'intérieur d'une entrée FormControl

J'ai un Angular 2 FormGroup généré dynamiquement avec plusieurs champs d'entrée FormControl. Certaines des entrées sont des dates, qui sont récupérées sur le serveur sous forme d'horodatages Unix.

Ce que je voudrais faire, c'est:

  1. pour pouvoir traduire l'horodatage unix en une forme lisible par l'homme, lorsque mon FormGroup est rempli, et aussi
  2. traduire la représentation humaine de la date en un horodatage Unix lorsque le formulaire est soumis.

La partie 1 est quelque peu simple, en utilisant le tube de date d'Angular comme ceci:

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

Où this.form est une référence au FormGroup et this.question est une classe wrapper personnalisée basée sur le didacticiel officiel sur les formulaires dynamiques:

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

Essayer de modifier l'entrée de date de cette façon ne fonctionnera pas car le canal essaiera constamment de transformer la valeur d'entrée, ce qui rendra l'entrée inutilisable s'il ne lève pas un argument non valide pour l'exception 'DatePipe' du canal.

Pour clarifier, je remplis mon formulaire en utilisant l'api FormGroup.patchValue(), et je soumets les données du formulaire en utilisant l'api FormGroup.getRawValue().

J'ai essayé d'utiliser un composant de sélecteur de date Angular 2, mais ils ont rendu mes énormes formulaires assez lents, donc je voudrais le faire sans sélecteurs de date personnalisés ni aucun widget dépendant de jQuery.

Merci d'avance.

11
ktsangop

Une façon de faire une telle chose serait de créer un composant pour votre entrée qui implémente ControlValueAccessor

Un pont entre un contrôle et un élément natif.

Un ControlValueAccessor résume les opérations d'écriture d'une nouvelle valeur dans un élément DOM représentant un contrôle d'entrée.

Veuillez consulter DefaultValueAccessor pour plus d'informations.

Quelque chose comme ça devrait faire l'affaire (non testé):

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

alors vous devriez pouvoir l'utiliser comme ceci:

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

ou

<my-input [(ngModel)]="myModel"></my-input>
10
n00dl3