Loading [MathJax]/jax/output/HTML-CSS/jax.js

Sunday, March 22, 2020

Data Validation using Decorator in Typescript

In index.html we have
1
2
3
4
5
<form>
  <input type="text" placeholder="Course Title" id="title" />
  <input type="text" placeholder="Price" id="price" />
  <button type="submit">Submit</button>
</form>
and inside our ts (transpiled into js file and link it into our index.html), we write:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
enum Validation {
  required = "required",
  positive = "positive"
}
 
interface ValidatorConfig {
  [property: string]: {
    [validatableProp: string]: Validation[]; //e.g., [Validation.required, Validation.positive]
  };
}
 
const registeredValidators: ValidatorConfig = {};
 
function Required(target: any, propName: string) {
  //we don't have propertyDescriptor for property, it exists only for methods
  registeredValidators[target.constructor.name] = {
    ...registeredValidators[target.constructor.name],
    [propName]: [Validation.required]
  };
}
 
function Positive(target: any, propName: string) {
  registeredValidators[target.constructor.name] = {
    ...registeredValidators[target.constructor.name],
    [propName]: [Validation.positive]
  };
}
 
function validate(obj: any) {
  const objValidatorConfig = registeredValidators[obj.constructor.name];
  if (!objValidatorConfig) {
    return true;
  } else {
    let validated = true;
    for (const prop in objValidatorConfig) {
      for (const validator of objValidatorConfig[prop]) {
        if (validator === (Validation.required as string)) {
          console.log("run?");
          validated = validated && obj[prop].trim().length > 0;
        }
        if (validator === (Validation.positive as string)) {
          validated = validated && obj[prop] > 0;
        }
      }
    }
    return validated;
  }
}
 
class Course {
  @Required
  public title: string;
 
  @Positive
  public price: number;
 
  constructor(t: string, p: number) {
    this.title = t;
    this.price = p;
  }
}
 
const courseForm = document.querySelector("form")!;
courseForm.addEventListener("submit", e => {
  e.preventDefault();
  const titleEl = document.getElementById("title") as HTMLInputElement;
  const priceEl = document.getElementById("price") as HTMLInputElement;
  const title = titleEl.value;
  const price = +priceEl.value;
  const newCourse = new Course(title, price);
 
  if (!validate(newCourse)) {
    alert("Invalid input, please try again!");
    return;
  }
 
  console.log(newCourse);
});

No comments:

Post a Comment