Configurar validación personalizada para la subida de archivos en el formulario de Angular no está funcionando como se espera.
Quiero implementar la validación de carga de archivos PDF. Si el archivo PDF cargado está protegido con contraseña, no debe ser permitido. Estoy utilizando Angular TypeScript.
A continuación se encuentra mi función de validación personalizada:
export function pdfFileValidator(file: File, fileExtension: string): AsyncValidatorFn {
return (control: AbstractControl): Observable<{ [key: string]: any } | null> => {
var res = false;
if (fileExtension.toLowerCase() === 'pdf') {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
var url = URL.createObjectURL(file);
const loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) { console.error(pdf) })
.catch((e: PasswordException) => {
console.error("El archivo está protegido con contraseña");
res = true;
}).finally(() => {
return {
'EncryptedFileViolated': res,
};
});
}
console.error("response =", res)
return of(null);
};
}
A continuación se encuentra mi función de validación establecida:
setFileValidators(fileSize: number, fileExtension: string, file:File) {
this.form.get('file')?.setValidators([FileSizeValidator(fileSize, this.maxSizeAllowedInMB),
FileExtensionValidator(fileExtension, ['pdf','jpg','png'])]);
this.form.get('file')?.addAsyncValidators(pdfFileValidator(file, fileExtension));
this.form.get('file')!.updateValueAndValidity();
console.error(this.form);
}
Cómo funciona actualmente:
Estas dos líneas se ejecutan antes de esperar la ejecución completa de la función pdfFileValidator
:
this.form.get('file')!.updateValueAndValidity();
console.error(this.form);
Y el formulario muestra estado = válido
.
Quiero que this.form.get('file')?.addAsyncValidators()
espere a que se complete la función pdfFileValidator
y luego ejecute la función updateValueAndValidity
.
¿Cómo podemos implementar esto?
davy.ai
Para asegurarnos de que
updateValueAndValidity()
se ejecute después de la finalización de la funciónpdfFileValidator()
, debemos utilizar el operadorswitchMap()
derxjs
.La función
setFileValidators()
modificada debería verse así:Aquí estamos utilizando
setAsyncValidators()
para aplicar la funciónpdfFileValidator()
como una función de validación asíncrona. La funciónpipe()
se utiliza para encadenar el operadorswitchMap()
.switchMap()
toma el resultado booleanores
devuelto porpdfFileValidator()
y genera un nuevo observableof({EncryptedFileViolated: res})
que emite un objeto con la claveEncryptedFileViolated
y el valorres
. Este observable generado se devuelve, y eventualmente será suscrito internamente por elAsyncValidator
.Por lo tanto, cuando el observable se complete, el resultado se pasará al método
updateValueAndValidity()
, que ahora debería ejecutarse solo después de la finalización de la funciónpdfFileValidator()
.