FormControls (à la fois modèle axé sur la et réactif) abonnez-vous pour les valeurs et écrire des valeurs via des Directives qui mettent en oeuvre ControlValueAccessor
. Jetez un oeil à la méthode selectValueAccessor, qui est utilisé dans toutes les directives nécessaires. Normal contrôles de saisie (par exemple, <input type="text">
) ou de ces zones de texte sont traitées par le DefaultValueAccessor. Un autre exemple est la CheckboxValueAccessor qui est appliqué à la case de contrôles de saisie.
Le travail n'est pas compliqué du tout. Nous avons juste besoin de mettre en œuvre une nouvelle valeur de l'accesseur pour la date de contrôles de saisie.
DateValueAccessor
est un joli nom:
// date-value-accessor.ts
import { Directive, ElementRef, HostListener, Renderer, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export const DATE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateValueAccessor),
multi: true
};
/**
* The accessor for writing a value and listening to changes on a date input element
*
* ### Example
* `<input type="date" name="myBirthday" ngModel useValueAsDate>`
*/
@Directive({
selector: '[useValueAsDate]',
providers: [DATE_VALUE_ACCESSOR]
})
export class DateValueAccessor implements ControlValueAccessor {
@HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => { };
@HostListener('blur', []) onTouched = () => { };
constructor(private _renderer: Renderer, private _elementRef: ElementRef) { }
writeValue(value: Date): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'valueAsDate', value);
}
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
setDisabledState(isDisabled: boolean): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
}
}
Nous attachons de l' DateValueAccessor
de la multi-fournisseur DATE_VALUE_ACCESSOR
, de sorte que selectValueAccessor pouvez le trouver.
La seule question est, qui sélecteur doit être utilisé. J'ai décidé pour une solution opt-in.
Ici le DateValueAccessor sélectionne sur l'attribut "useValueAsDate".
<input type="date" name="myBirthday" ngModel useValueAsDate>
OR
<input type="date" name="myBirthday" [(ngModel)]="myBirthday" useValueAsDate>
OR
<input type="date" formControlName="myBirthday" useValueAsDate>
Il est également possible de corriger le défaut de mise en œuvre.
Le sélecteur suivant activer la fonctionnalité comme par magie.
// this selector changes the previous behavior silently and might break existing code
selector: 'input[type=date][formControlName],input[type=date][formControl],input[type=date][ngModel]'
Mais s'il vous plaît être conscient que cela peut casser implémentations existantes qui utilisent de l'ancien comportement. Donc je pencherais pour l'opt-in version!
C'est tout le MNP et Github
Pour votre commodité, j'ai créé le projet angular-data-value-accessor
sur Github.
Il y a aussi un MNP forfait disponible:
npm install --save angular-date-value-accessor
Ensuite, il suffit d'importer le module via NgModule:
// app.module.ts
import { DateValueAccessorModule } from 'angular-date-value-accessor';
@NgModule({
imports: [
DateValueAccessorModule
]
})
export class AppModule { }
Maintenant, vous pouvez appliquer la "useValueAsDate" votre date de contrôles de saisie.
Démo
Bien sûr, il y a une démo à:
http://johanneshoppe.github.io/angular-date-value-accessor/