Angular2: la validación de no se activará al cambiar el archivo para cargar

Angular 2 parece tener problemas con la ejecución de la validación cuando cambia la entrada de un archivo.

Hice una prueba para ilustrar este problema:

Hago una forma Grupo como

this.frm = new FormGroup({ file: new FormControl("", this.validateFile) }); 

Y en la función validateFile lanzo una alerta y registro a la consola:

 public validateFile(formControl: FormControl): {[key: string]: any; } { alert('Validation ran'); console.log('Validation ran'); } 

Plunkr para ilustrar el problema: https://plnkr.co/edit/Pgcg4IkejgaH5YgbY3Ar?p=preview

La validación se ejecutará al inicializar la página, pero no se ejecutará cada vez que cambie el archivo que se cargará.

¿Hay alguna solución a este problema?

Lo arreglé usando la respuesta kemsky y el comentario de Sebastien. Hice un ngValueAccessor que se registra en cada entrada con tipo de archivo.

Plunkr se puede encontrar aquí .

Código más relevante + explicación debajo:

Esto agrega un ControlValueAccessor para entradas de archivo que podrían ser parte del propio framework angular algún día ( # 7341 ). Una entrada de archivo funciona de manera diferente a otros controles. Este fragmento de código se asegura de que los archivos seleccionados se lean como el valor:

 import {Directive} from "@angular/core"; import {NG_VALUE_ACCESSOR, ControlValueAccessor} from "@angular/forms"; @Directive({ selector: "input[type=file]", host : { "(change)" : "onChange($event.target.files)", "(blur)": "onTouched()" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessor, multi: true } ] }) export class FileValueAccessor implements ControlValueAccessor { value: any; onChange = (_) => {}; onTouched = () => {}; writeValue(value) {} registerOnChange(fn: any) { this.onChange = fn; } registerOnTouched(fn: any) { this.onTouched = fn; } } 

Y para la validación ‘requerida’ hice un validador que uso al agregar el método de validación estática al archivo FormControl for ReactiveForms. (o como una directiva para formularios basados ​​en plantillas).

 import {Directive} from "@angular/core"; import {NG_VALIDATORS, Validator, FormControl} from "@angular/forms"; @Directive({ selector: "[requiredFile]", providers: [ { provide: NG_VALIDATORS, useExisting: FileValidator, multi: true }, ] }) export class FileValidator implements Validator { static validate(c: FormControl): {[key: string]: any} { return c.value == null || c.value.length == 0 ? { "required" : true} : null; } validate(c: FormControl): {[key: string]: any} { return FileValidator.validate(c); } } 

La construcción de mi formulario se ve así:

 private buildForm() { this.frm = new FormGroup({ file: new FormControl("", [FileValidator.validate]) }); } 

Y para el html:

  

Angular 4+ ha cambiado sus enlaces de host.

 import { Directive, HostListener } from "@angular/core"; import { NG_VALUE_ACCESSOR, ControlValueAccessor } from "@angular/forms"; @Directive({ selector: "input[type=file]", providers: [ {provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessorDirective, multi: true} ] }) export class FileValueAccessorDirective implements ControlValueAccessor { @HostListener('change', ['$event.target.files']) onChange = (_) => {}; @HostListener('blur') onTouched = () => {}; writeValue(value) {} registerOnChange(fn: any) { this.onChange = fn; } registerOnTouched(fn: any) { this.onTouched = fn; } } 

La entrada con tipo de file no es compatible actualmente, vea # 7341