es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para asegurarnos de que updateValueAndValidity() se ejecute después de la finalización de la función pdfFileValidator(), debemos utilizar el operador switchMap() de rxjs.

    La función setFileValidators() modificada debería verse así:

    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')?.setAsyncValidators(pdfFileValidator(file,fileExtension).pipe(
        switchMap(res => {
          return of({
            EncryptedFileViolated: res
          });
        })
      ));
    
      this.form.get('file')!.updateValueAndValidity();
      console.log(this.form);
    }
    

    Aquí estamos utilizando setAsyncValidators() para aplicar la función pdfFileValidator() como una función de validación asíncrona. La función pipe() se utiliza para encadenar el operador switchMap().

    switchMap() toma el resultado booleano res devuelto por pdfFileValidator() y genera un nuevo observable of({EncryptedFileViolated: res}) que emite un objeto con la clave EncryptedFileViolated y el valor res. Este observable generado se devuelve, y eventualmente será suscrito internamente por el AsyncValidator.

    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ón pdfFileValidator().

Comments are closed.