12/08/2018, 16:25

Image Validation On Angular 2/4

Chào mọi người, hôm nay mình sẽ hướng dẫn mọi người viết những validator cơ bản cho image hay bất kỳ 1 dạng file upload nào trong angular 2. Như mọi người đã biết, Angular2 cung cấp cho ta 1 bộ thư viện về validator (bao gồm cả sync và async validator). Cách viết cơ bản với 1 formControl như sau: ...

Chào mọi người, hôm nay mình sẽ hướng dẫn mọi người viết những validator cơ bản cho image hay bất kỳ 1 dạng file upload nào trong angular 2. Như mọi người đã biết, Angular2 cung cấp cho ta 1 bộ thư viện về validator (bao gồm cả sync và async validator). Cách viết cơ bản với 1 formControl như sau:

this.signInForm = this.formBuilder.group({
  email: [', [Validators.required,
    Validators.maxLength(valConst.EMAIL_MAX_LENGTH),
    Validators.pattern(valConst.EMAIL_PATTERN)]],
  password: [', [Validators.required,
    Validators.maxLength(valConst.PASSWORD_MAX_LENGTH),
    Validators.pattern(valConst.PASSWORD_PATTERN)]],
});

Contructor của 1 formControl như sau:

constructor(formState: any = null, validatorOrOpts?: 
ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, asyncValidator?: 
AsyncValidatorFn|AsyncValidatorFn[]|null)

Với contructor trên và ví dụ mình đã viết thì signInform của mình mới chỉ khởi tạo giá trị mặc định, và 1 vài sync validator. nghĩa là ngay khi giá trị được nhập giá trị ấy sẽ chạy qua ngay những validator kia để xác định trạng thái của formControl. Vậy với những trường giá trị mà giá trị của nó không thể ngay lập tức được load đến (load từ server, load từ local computer) thì sẽ ra sao, đó là sự bất đồng bộ trong luồng chạy của javascript, Angular đồng thời cũng hỗ trợ ta việc xử lý validate bất đồng bộ. Nhìn trên contructor thì đó là

AsyncValidatorFn|AsyncValidatorFn[]|null

Vậy liên quan gì đến ảnh. trước hết để xác định 1 ảnh có valid hay ko ở client, ta cần load ảnh để đọc thông số ảnh (định dạng, kích thứớc, size). và việc load ảnh này là bất đồng bộ. Ta đặt ra đề bài cần chạy validate cho 3 thông số ảnh: Size, Extension và Dimension Trong 3 thông số kia, có 2 thông số có thể đọc được ngay (Size và Extension). Nên ta đặt 2 thông số này vào trong SyncValidator của form

this.informationForm = this.formBuilder.group({
  image: [', [ImageValidator.imageSizeValidator(100000),
    ImageValidator.imageExtensionValidator(['image/jpeg', 'image/png'])]]
});

Tạo 1 custom validator như sau:

import { FormControl } from '@angular/forms';

export class ImageValidator {
  static imageSizeValidator(maxSize: number) {
    return function (input: FormControl) {
      if (input.value[0]) {
        return input.value[0].size > maxSize ? {maxSize: true} : null;
      }
      return null;
    };
  }

  static imageExtensionValidator(whiteListImageExtension: Array<string>) {
    return function(input: FormControl) {
      if (input.value[0]) {
        return whiteListImageExtension.includes(input.value[0].type) ? null : {extension: true};
      }
      return null;
    };
  }
}

Và giờ là đến xử lý validate bất đồng bộ cho thông số kích thứớc ảnh. Đề bài là ảnh không được bé hơn 300x300 px Do là xử lý bất đồng bộ nên dạng trả về của Validator sẽ là 1 Promise. Bổ sung vào file custom validator

static imageDimensionValidator(imageMinHeight: number, imageMinWidth: number) {
    return function(input: FormControl) {
      return new Promise(resolve => {
        if (input.value[0]) {
          const fr = new FileReader;
          fr.onload = function () {
            const image = new Image;
            image.onload = function () {
              if (image.awidth < imageMinWidth || image.height < imageMinHeight) {
                return resolve({dimension: true});
              }
              return resolve(null);
            };
            image.src = fr.result;
          };
          fr.readAsDataURL(input.value[0]);
        } else {
          return resolve(null);
        }
      });
    };
  }

Khởi tạo form hoàn thiện như sau:

this.informationForm = this.formBuilder.group({
  image: [', [ImageValidator.imageSizeValidator(100000),
    ImageValidator.imageExtensionValidator(['image/jpeg', 'image/png'])],
    ImageValidator.imageDimensionValidator(300, 300)]
});

Vậy là xong. Ảnh của bạn sẽ chạy qua đủ tất cả validator. để ý nêú up ảnh nặng quá browser sẽ mất chút thời gian để hiện ra validation về dimension đấy.

0