Project

General

Profile

Form CRUD - Employees » History » Version 2

Lê Sĩ Quý, 08/29/2025 06:27 PM

1 1 Lê Sĩ Quý
# Form CRUD - Employees
2
3
# Form List - Employees
4
5
{{TOC}}
6
7
## JSON Schema
8
9
``` javascript
10
{
11
  "display": "form",
12
  "components": [
13
    {
14
      "title": "<strong>New Employee</strong>",
15
      "collapsible": false,
16
      "key": "NewEmployee",
17
      "type": "panel",
18
      "label": "Panel",
19
      "input": false,
20
      "tableView": false,
21
      "components": [
22
        {
23
          "label": "Employee ID",
24
          "applyMaskOn": "change",
25
          "tableView": true,
26
          "protected": true,
27
          "customDefaultValue": "value = `EMP${moment().unix().toString().slice(-7)}`;",
28
          "validate": {
29
            "required": true
30
          },
31
          "validateWhenHidden": false,
32
          "key": "EmployeeID",
33
          "type": "textfield",
34
          "input": true
35
        },
36
        {
37
          "label": "Title Of Courtesy",
38
          "widget": "choicesjs",
39
          "tableView": true,
40
          "data": {
41
            "values": [
42
              {
43
                "label": "Mr.",
44
                "value": "Mr."
45
              },
46
              {
47
                "label": "Ms.",
48
                "value": "Ms."
49
              },
50
              {
51
                "label": "Dr.",
52
                "value": "Dr."
53
              },
54
              {
55
                "label": "Mrs.",
56
                "value": "Mrs."
57
              }
58
            ]
59
          },
60
          "validate": {
61
            "required": true
62
          },
63
          "validateWhenHidden": false,
64
          "key": "TitleOfCourtesy",
65
          "type": "select",
66
          "input": true
67
        },
68
        {
69
          "label": "Last Name",
70
          "applyMaskOn": "change",
71
          "tableView": true,
72
          "validate": {
73
            "required": true
74
          },
75
          "validateWhenHidden": false,
76
          "key": "LastName",
77
          "type": "textfield",
78
          "input": true
79
        },
80
        {
81
          "label": "First Name",
82
          "applyMaskOn": "change",
83
          "tableView": true,
84
          "validate": {
85
            "required": true
86
          },
87
          "validateWhenHidden": false,
88
          "key": "FirstName",
89
          "type": "textfield",
90
          "input": true
91
        },
92
        {
93
          "label": "Title",
94
          "widget": "choicesjs",
95
          "tableView": true,
96
          "data": {
97
            "values": [
98
              {
99
                "label": "Sales Manager",
100
                "value": "Sales Manager"
101
              },
102
              {
103
                "label": "Inside Sales Coordinator",
104
                "value": "Inside Sales Coordinator"
105
              },
106
              {
107
                "label": "Sales Representative",
108
                "value": "Sales Representative"
109
              },
110
              {
111
                "label": "Vice President, Sales",
112
                "value": "Vice President, Sales"
113
              }
114
            ]
115
          },
116
          "validateWhenHidden": false,
117
          "key": "Title",
118
          "type": "select",
119
          "input": true
120
        },
121
        {
122
          "label": "Birth Date",
123
          "format": "yyyy-MM-dd",
124
          "tableView": false,
125
          "datePicker": {
126
            "disableWeekends": false,
127
            "disableWeekdays": false
128
          },
129
          "enableTime": false,
130
          "validate": {
131
            "required": true
132
          },
133
          "enableMinDateInput": false,
134
          "enableMaxDateInput": false,
135
          "validateWhenHidden": false,
136
          "key": "BirthDate",
137
          "type": "datetime",
138
          "input": true,
139
          "widget": {
140
            "type": "calendar",
141
            "displayInTimezone": "viewer",
142
            "locale": "en",
143
            "useLocaleSettings": false,
144
            "allowInput": true,
145
            "mode": "single",
146
            "enableTime": false,
147
            "noCalendar": false,
148
            "format": "yyyy-MM-dd",
149
            "hourIncrement": 1,
150
            "minuteIncrement": 1,
151
            "time_24hr": false,
152
            "minDate": null,
153
            "disableWeekends": false,
154
            "disableWeekdays": false,
155
            "maxDate": null
156
          }
157
        },
158
        {
159
          "label": "Hire Date",
160
          "format": "yyyy-MM-dd",
161
          "tableView": false,
162
          "datePicker": {
163
            "disableWeekends": false,
164
            "disableWeekdays": false
165
          },
166
          "enableTime": false,
167
          "validate": {
168
            "required": true
169
          },
170
          "enableMinDateInput": false,
171
          "enableMaxDateInput": false,
172
          "validateWhenHidden": false,
173
          "key": "HireDate",
174
          "type": "datetime",
175
          "input": true,
176
          "widget": {
177
            "type": "calendar",
178
            "displayInTimezone": "viewer",
179
            "locale": "en",
180
            "useLocaleSettings": false,
181
            "allowInput": true,
182
            "mode": "single",
183
            "enableTime": false,
184
            "noCalendar": false,
185
            "format": "yyyy-MM-dd",
186
            "hourIncrement": 1,
187
            "minuteIncrement": 1,
188
            "time_24hr": false,
189
            "minDate": null,
190
            "disableWeekends": false,
191
            "disableWeekdays": false,
192
            "maxDate": null
193
          }
194
        },
195
        {
196
          "label": "Address",
197
          "applyMaskOn": "change",
198
          "tableView": true,
199
          "validate": {
200
            "required": true
201
          },
202
          "validateWhenHidden": false,
203
          "key": "Address",
204
          "type": "textfield",
205
          "input": true
206
        },
207
        {
208
          "label": "City",
209
          "applyMaskOn": "change",
210
          "tableView": true,
211
          "validateWhenHidden": false,
212
          "key": "City",
213
          "type": "textfield",
214
          "input": true
215
        },
216
        {
217
          "label": "Region",
218
          "applyMaskOn": "change",
219
          "tableView": true,
220
          "validateWhenHidden": false,
221
          "key": "Region",
222
          "type": "textfield",
223
          "input": true
224
        },
225
        {
226
          "label": "Postal Code",
227
          "applyMaskOn": "change",
228
          "tableView": true,
229
          "validateWhenHidden": false,
230
          "key": "PostalCode",
231
          "type": "textfield",
232
          "input": true
233
        },
234
        {
235
          "label": "Country",
236
          "widget": "choicesjs",
237
          "tableView": true,
238
          "dataSrc": "json",
239
          "data": {
240
            "json": [
241
              {
242
                "name": "Afghanistan",
243
                "code": "AF"
244
              },
245
              {
246
                "name": "Åland Islands",
247
                "code": "AX"
248
              },
249
              {
250
                "name": "Albania",
251
                "code": "AL"
252
              },
253
              {
254
                "name": "Algeria",
255
                "code": "DZ"
256
              },
257
              {
258
                "name": "American Samoa",
259
                "code": "AS"
260
              },
261
              {
262
                "name": "AndorrA",
263
                "code": "AD"
264
              },
265
              {
266
                "name": "Angola",
267
                "code": "AO"
268
              },
269
              {
270
                "name": "Anguilla",
271
                "code": "AI"
272
              },
273
              {
274
                "name": "Antarctica",
275
                "code": "AQ"
276
              },
277
              {
278
                "name": "Antigua and Barbuda",
279
                "code": "AG"
280
              },
281
              {
282
                "name": "Argentina",
283
                "code": "AR"
284
              },
285
              {
286
                "name": "Armenia",
287
                "code": "AM"
288
              },
289
              {
290
                "name": "Aruba",
291
                "code": "AW"
292
              },
293
              {
294
                "name": "Australia",
295
                "code": "AU"
296
              },
297
              {
298
                "name": "Austria",
299
                "code": "AT"
300
              },
301
              {
302
                "name": "Azerbaijan",
303
                "code": "AZ"
304
              },
305
              {
306
                "name": "Bahamas",
307
                "code": "BS"
308
              },
309
              {
310
                "name": "Bahrain",
311
                "code": "BH"
312
              },
313
              {
314
                "name": "Bangladesh",
315
                "code": "BD"
316
              },
317
              {
318
                "name": "Barbados",
319
                "code": "BB"
320
              },
321
              {
322
                "name": "Belarus",
323
                "code": "BY"
324
              },
325
              {
326
                "name": "Belgium",
327
                "code": "BE"
328
              },
329
              {
330
                "name": "Belize",
331
                "code": "BZ"
332
              },
333
              {
334
                "name": "Benin",
335
                "code": "BJ"
336
              },
337
              {
338
                "name": "Bermuda",
339
                "code": "BM"
340
              },
341
              {
342
                "name": "Bhutan",
343
                "code": "BT"
344
              },
345
              {
346
                "name": "Bolivia",
347
                "code": "BO"
348
              },
349
              {
350
                "name": "Bosnia and Herzegovina",
351
                "code": "BA"
352
              },
353
              {
354
                "name": "Botswana",
355
                "code": "BW"
356
              },
357
              {
358
                "name": "Bouvet Island",
359
                "code": "BV"
360
              },
361
              {
362
                "name": "Brazil",
363
                "code": "BR"
364
              },
365
              {
366
                "name": "British Indian Ocean Territory",
367
                "code": "IO"
368
              },
369
              {
370
                "name": "Brunei Darussalam",
371
                "code": "BN"
372
              },
373
              {
374
                "name": "Bulgaria",
375
                "code": "BG"
376
              },
377
              {
378
                "name": "Burkina Faso",
379
                "code": "BF"
380
              },
381
              {
382
                "name": "Burundi",
383
                "code": "BI"
384
              },
385
              {
386
                "name": "Cambodia",
387
                "code": "KH"
388
              },
389
              {
390
                "name": "Cameroon",
391
                "code": "CM"
392
              },
393
              {
394
                "name": "Canada",
395
                "code": "CA"
396
              },
397
              {
398
                "name": "Cape Verde",
399
                "code": "CV"
400
              },
401
              {
402
                "name": "Cayman Islands",
403
                "code": "KY"
404
              },
405
              {
406
                "name": "Central African Republic",
407
                "code": "CF"
408
              },
409
              {
410
                "name": "Chad",
411
                "code": "TD"
412
              },
413
              {
414
                "name": "Chile",
415
                "code": "CL"
416
              },
417
              {
418
                "name": "China",
419
                "code": "CN"
420
              },
421
              {
422
                "name": "Christmas Island",
423
                "code": "CX"
424
              },
425
              {
426
                "name": "Cocos (Keeling) Islands",
427
                "code": "CC"
428
              },
429
              {
430
                "name": "Colombia",
431
                "code": "CO"
432
              },
433
              {
434
                "name": "Comoros",
435
                "code": "KM"
436
              },
437
              {
438
                "name": "Congo",
439
                "code": "CG"
440
              },
441
              {
442
                "name": "Congo, The Democratic Republic of the",
443
                "code": "CD"
444
              },
445
              {
446
                "name": "Cook Islands",
447
                "code": "CK"
448
              },
449
              {
450
                "name": "Costa Rica",
451
                "code": "CR"
452
              },
453
              {
454
                "name": "Cote D\"Ivoire",
455
                "code": "CI"
456
              },
457
              {
458
                "name": "Croatia",
459
                "code": "HR"
460
              },
461
              {
462
                "name": "Cuba",
463
                "code": "CU"
464
              },
465
              {
466
                "name": "Cyprus",
467
                "code": "CY"
468
              },
469
              {
470
                "name": "Czech Republic",
471
                "code": "CZ"
472
              },
473
              {
474
                "name": "Denmark",
475
                "code": "DK"
476
              },
477
              {
478
                "name": "Djibouti",
479
                "code": "DJ"
480
              },
481
              {
482
                "name": "Dominica",
483
                "code": "DM"
484
              },
485
              {
486
                "name": "Dominican Republic",
487
                "code": "DO"
488
              },
489
              {
490
                "name": "Ecuador",
491
                "code": "EC"
492
              },
493
              {
494
                "name": "Egypt",
495
                "code": "EG"
496
              },
497
              {
498
                "name": "El Salvador",
499
                "code": "SV"
500
              },
501
              {
502
                "name": "Equatorial Guinea",
503
                "code": "GQ"
504
              },
505
              {
506
                "name": "Eritrea",
507
                "code": "ER"
508
              },
509
              {
510
                "name": "Estonia",
511
                "code": "EE"
512
              },
513
              {
514
                "name": "Ethiopia",
515
                "code": "ET"
516
              },
517
              {
518
                "name": "Falkland Islands (Malvinas)",
519
                "code": "FK"
520
              },
521
              {
522
                "name": "Faroe Islands",
523
                "code": "FO"
524
              },
525
              {
526
                "name": "Fiji",
527
                "code": "FJ"
528
              },
529
              {
530
                "name": "Finland",
531
                "code": "FI"
532
              },
533
              {
534
                "name": "France",
535
                "code": "FR"
536
              },
537
              {
538
                "name": "French Guiana",
539
                "code": "GF"
540
              },
541
              {
542
                "name": "French Polynesia",
543
                "code": "PF"
544
              },
545
              {
546
                "name": "French Southern Territories",
547
                "code": "TF"
548
              },
549
              {
550
                "name": "Gabon",
551
                "code": "GA"
552
              },
553
              {
554
                "name": "Gambia",
555
                "code": "GM"
556
              },
557
              {
558
                "name": "Georgia",
559
                "code": "GE"
560
              },
561
              {
562
                "name": "Germany",
563
                "code": "DE"
564
              },
565
              {
566
                "name": "Ghana",
567
                "code": "GH"
568
              },
569
              {
570
                "name": "Gibraltar",
571
                "code": "GI"
572
              },
573
              {
574
                "name": "Greece",
575
                "code": "GR"
576
              },
577
              {
578
                "name": "Greenland",
579
                "code": "GL"
580
              },
581
              {
582
                "name": "Grenada",
583
                "code": "GD"
584
              },
585
              {
586
                "name": "Guadeloupe",
587
                "code": "GP"
588
              },
589
              {
590
                "name": "Guam",
591
                "code": "GU"
592
              },
593
              {
594
                "name": "Guatemala",
595
                "code": "GT"
596
              },
597
              {
598
                "name": "Guernsey",
599
                "code": "GG"
600
              },
601
              {
602
                "name": "Guinea",
603
                "code": "GN"
604
              },
605
              {
606
                "name": "Guinea-Bissau",
607
                "code": "GW"
608
              },
609
              {
610
                "name": "Guyana",
611
                "code": "GY"
612
              },
613
              {
614
                "name": "Haiti",
615
                "code": "HT"
616
              },
617
              {
618
                "name": "Heard Island and Mcdonald Islands",
619
                "code": "HM"
620
              },
621
              {
622
                "name": "Holy See (Vatican City State)",
623
                "code": "VA"
624
              },
625
              {
626
                "name": "Honduras",
627
                "code": "HN"
628
              },
629
              {
630
                "name": "Hong Kong",
631
                "code": "HK"
632
              },
633
              {
634
                "name": "Hungary",
635
                "code": "HU"
636
              },
637
              {
638
                "name": "Iceland",
639
                "code": "IS"
640
              },
641
              {
642
                "name": "India",
643
                "code": "IN"
644
              },
645
              {
646
                "name": "Indonesia",
647
                "code": "ID"
648
              },
649
              {
650
                "name": "Iran, Islamic Republic Of",
651
                "code": "IR"
652
              },
653
              {
654
                "name": "Iraq",
655
                "code": "IQ"
656
              },
657
              {
658
                "name": "Ireland",
659
                "code": "IE"
660
              },
661
              {
662
                "name": "Isle of Man",
663
                "code": "IM"
664
              },
665
              {
666
                "name": "Israel",
667
                "code": "IL"
668
              },
669
              {
670
                "name": "Italy",
671
                "code": "IT"
672
              },
673
              {
674
                "name": "Jamaica",
675
                "code": "JM"
676
              },
677
              {
678
                "name": "Japan",
679
                "code": "JP"
680
              },
681
              {
682
                "name": "Jersey",
683
                "code": "JE"
684
              },
685
              {
686
                "name": "Jordan",
687
                "code": "JO"
688
              },
689
              {
690
                "name": "Kazakhstan",
691
                "code": "KZ"
692
              },
693
              {
694
                "name": "Kenya",
695
                "code": "KE"
696
              },
697
              {
698
                "name": "Kiribati",
699
                "code": "KI"
700
              },
701
              {
702
                "name": "Korea, Democratic People\"S Republic of",
703
                "code": "KP"
704
              },
705
              {
706
                "name": "Korea, Republic of",
707
                "code": "KR"
708
              },
709
              {
710
                "name": "Kuwait",
711
                "code": "KW"
712
              },
713
              {
714
                "name": "Kyrgyzstan",
715
                "code": "KG"
716
              },
717
              {
718
                "name": "Lao People\"S Democratic Republic",
719
                "code": "LA"
720
              },
721
              {
722
                "name": "Latvia",
723
                "code": "LV"
724
              },
725
              {
726
                "name": "Lebanon",
727
                "code": "LB"
728
              },
729
              {
730
                "name": "Lesotho",
731
                "code": "LS"
732
              },
733
              {
734
                "name": "Liberia",
735
                "code": "LR"
736
              },
737
              {
738
                "name": "Libyan Arab Jamahiriya",
739
                "code": "LY"
740
              },
741
              {
742
                "name": "Liechtenstein",
743
                "code": "LI"
744
              },
745
              {
746
                "name": "Lithuania",
747
                "code": "LT"
748
              },
749
              {
750
                "name": "Luxembourg",
751
                "code": "LU"
752
              },
753
              {
754
                "name": "Macao",
755
                "code": "MO"
756
              },
757
              {
758
                "name": "Macedonia, The Former Yugoslav Republic of",
759
                "code": "MK"
760
              },
761
              {
762
                "name": "Madagascar",
763
                "code": "MG"
764
              },
765
              {
766
                "name": "Malawi",
767
                "code": "MW"
768
              },
769
              {
770
                "name": "Malaysia",
771
                "code": "MY"
772
              },
773
              {
774
                "name": "Maldives",
775
                "code": "MV"
776
              },
777
              {
778
                "name": "Mali",
779
                "code": "ML"
780
              },
781
              {
782
                "name": "Malta",
783
                "code": "MT"
784
              },
785
              {
786
                "name": "Marshall Islands",
787
                "code": "MH"
788
              },
789
              {
790
                "name": "Martinique",
791
                "code": "MQ"
792
              },
793
              {
794
                "name": "Mauritania",
795
                "code": "MR"
796
              },
797
              {
798
                "name": "Mauritius",
799
                "code": "MU"
800
              },
801
              {
802
                "name": "Mayotte",
803
                "code": "YT"
804
              },
805
              {
806
                "name": "Mexico",
807
                "code": "MX"
808
              },
809
              {
810
                "name": "Micronesia, Federated States of",
811
                "code": "FM"
812
              },
813
              {
814
                "name": "Moldova, Republic of",
815
                "code": "MD"
816
              },
817
              {
818
                "name": "Monaco",
819
                "code": "MC"
820
              },
821
              {
822
                "name": "Mongolia",
823
                "code": "MN"
824
              },
825
              {
826
                "name": "Montserrat",
827
                "code": "MS"
828
              },
829
              {
830
                "name": "Morocco",
831
                "code": "MA"
832
              },
833
              {
834
                "name": "Mozambique",
835
                "code": "MZ"
836
              },
837
              {
838
                "name": "Myanmar",
839
                "code": "MM"
840
              },
841
              {
842
                "name": "Namibia",
843
                "code": "NA"
844
              },
845
              {
846
                "name": "Nauru",
847
                "code": "NR"
848
              },
849
              {
850
                "name": "Nepal",
851
                "code": "NP"
852
              },
853
              {
854
                "name": "Netherlands",
855
                "code": "NL"
856
              },
857
              {
858
                "name": "Netherlands Antilles",
859
                "code": "AN"
860
              },
861
              {
862
                "name": "New Caledonia",
863
                "code": "NC"
864
              },
865
              {
866
                "name": "New Zealand",
867
                "code": "NZ"
868
              },
869
              {
870
                "name": "Nicaragua",
871
                "code": "NI"
872
              },
873
              {
874
                "name": "Niger",
875
                "code": "NE"
876
              },
877
              {
878
                "name": "Nigeria",
879
                "code": "NG"
880
              },
881
              {
882
                "name": "Niue",
883
                "code": "NU"
884
              },
885
              {
886
                "name": "Norfolk Island",
887
                "code": "NF"
888
              },
889
              {
890
                "name": "Northern Mariana Islands",
891
                "code": "MP"
892
              },
893
              {
894
                "name": "Norway",
895
                "code": "NO"
896
              },
897
              {
898
                "name": "Oman",
899
                "code": "OM"
900
              },
901
              {
902
                "name": "Pakistan",
903
                "code": "PK"
904
              },
905
              {
906
                "name": "Palau",
907
                "code": "PW"
908
              },
909
              {
910
                "name": "Palestinian Territory, Occupied",
911
                "code": "PS"
912
              },
913
              {
914
                "name": "Panama",
915
                "code": "PA"
916
              },
917
              {
918
                "name": "Papua New Guinea",
919
                "code": "PG"
920
              },
921
              {
922
                "name": "Paraguay",
923
                "code": "PY"
924
              },
925
              {
926
                "name": "Peru",
927
                "code": "PE"
928
              },
929
              {
930
                "name": "Philippines",
931
                "code": "PH"
932
              },
933
              {
934
                "name": "Pitcairn",
935
                "code": "PN"
936
              },
937
              {
938
                "name": "Poland",
939
                "code": "PL"
940
              },
941
              {
942
                "name": "Portugal",
943
                "code": "PT"
944
              },
945
              {
946
                "name": "Puerto Rico",
947
                "code": "PR"
948
              },
949
              {
950
                "name": "Qatar",
951
                "code": "QA"
952
              },
953
              {
954
                "name": "Reunion",
955
                "code": "RE"
956
              },
957
              {
958
                "name": "Romania",
959
                "code": "RO"
960
              },
961
              {
962
                "name": "Russian Federation",
963
                "code": "RU"
964
              },
965
              {
966
                "name": "RWANDA",
967
                "code": "RW"
968
              },
969
              {
970
                "name": "Saint Helena",
971
                "code": "SH"
972
              },
973
              {
974
                "name": "Saint Kitts and Nevis",
975
                "code": "KN"
976
              },
977
              {
978
                "name": "Saint Lucia",
979
                "code": "LC"
980
              },
981
              {
982
                "name": "Saint Pierre and Miquelon",
983
                "code": "PM"
984
              },
985
              {
986
                "name": "Saint Vincent and the Grenadines",
987
                "code": "VC"
988
              },
989
              {
990
                "name": "Samoa",
991
                "code": "WS"
992
              },
993
              {
994
                "name": "San Marino",
995
                "code": "SM"
996
              },
997
              {
998
                "name": "Sao Tome and Principe",
999
                "code": "ST"
1000
              },
1001
              {
1002
                "name": "Saudi Arabia",
1003
                "code": "SA"
1004
              },
1005
              {
1006
                "name": "Senegal",
1007
                "code": "SN"
1008
              },
1009
              {
1010
                "name": "Serbia and Montenegro",
1011
                "code": "CS"
1012
              },
1013
              {
1014
                "name": "Seychelles",
1015
                "code": "SC"
1016
              },
1017
              {
1018
                "name": "Sierra Leone",
1019
                "code": "SL"
1020
              },
1021
              {
1022
                "name": "Singapore",
1023
                "code": "SG"
1024
              },
1025
              {
1026
                "name": "Slovakia",
1027
                "code": "SK"
1028
              },
1029
              {
1030
                "name": "Slovenia",
1031
                "code": "SI"
1032
              },
1033
              {
1034
                "name": "Solomon Islands",
1035
                "code": "SB"
1036
              },
1037
              {
1038
                "name": "Somalia",
1039
                "code": "SO"
1040
              },
1041
              {
1042
                "name": "South Africa",
1043
                "code": "ZA"
1044
              },
1045
              {
1046
                "name": "South Georgia and the South Sandwich Islands",
1047
                "code": "GS"
1048
              },
1049
              {
1050
                "name": "Spain",
1051
                "code": "ES"
1052
              },
1053
              {
1054
                "name": "Sri Lanka",
1055
                "code": "LK"
1056
              },
1057
              {
1058
                "name": "Sudan",
1059
                "code": "SD"
1060
              },
1061
              {
1062
                "name": "Suriname",
1063
                "code": "SR"
1064
              },
1065
              {
1066
                "name": "Svalbard and Jan Mayen",
1067
                "code": "SJ"
1068
              },
1069
              {
1070
                "name": "Swaziland",
1071
                "code": "SZ"
1072
              },
1073
              {
1074
                "name": "Sweden",
1075
                "code": "SE"
1076
              },
1077
              {
1078
                "name": "Switzerland",
1079
                "code": "CH"
1080
              },
1081
              {
1082
                "name": "Syrian Arab Republic",
1083
                "code": "SY"
1084
              },
1085
              {
1086
                "name": "Taiwan",
1087
                "code": "TW"
1088
              },
1089
              {
1090
                "name": "Tajikistan",
1091
                "code": "TJ"
1092
              },
1093
              {
1094
                "name": "Tanzania, United Republic of",
1095
                "code": "TZ"
1096
              },
1097
              {
1098
                "name": "Thailand",
1099
                "code": "TH"
1100
              },
1101
              {
1102
                "name": "Timor-Leste",
1103
                "code": "TL"
1104
              },
1105
              {
1106
                "name": "Togo",
1107
                "code": "TG"
1108
              },
1109
              {
1110
                "name": "Tokelau",
1111
                "code": "TK"
1112
              },
1113
              {
1114
                "name": "Tonga",
1115
                "code": "TO"
1116
              },
1117
              {
1118
                "name": "Trinidad and Tobago",
1119
                "code": "TT"
1120
              },
1121
              {
1122
                "name": "Tunisia",
1123
                "code": "TN"
1124
              },
1125
              {
1126
                "name": "Turkey",
1127
                "code": "TR"
1128
              },
1129
              {
1130
                "name": "Turkmenistan",
1131
                "code": "TM"
1132
              },
1133
              {
1134
                "name": "Turks and Caicos Islands",
1135
                "code": "TC"
1136
              },
1137
              {
1138
                "name": "Tuvalu",
1139
                "code": "TV"
1140
              },
1141
              {
1142
                "name": "Uganda",
1143
                "code": "UG"
1144
              },
1145
              {
1146
                "name": "Ukraine",
1147
                "code": "UA"
1148
              },
1149
              {
1150
                "name": "United Arab Emirates",
1151
                "code": "AE"
1152
              },
1153
              {
1154
                "name": "United Kingdom",
1155
                "code": "GB"
1156
              },
1157
              {
1158
                "name": "United States",
1159
                "code": "US"
1160
              },
1161
              {
1162
                "name": "United States Minor Outlying Islands",
1163
                "code": "UM"
1164
              },
1165
              {
1166
                "name": "Uruguay",
1167
                "code": "UY"
1168
              },
1169
              {
1170
                "name": "Uzbekistan",
1171
                "code": "UZ"
1172
              },
1173
              {
1174
                "name": "Vanuatu",
1175
                "code": "VU"
1176
              },
1177
              {
1178
                "name": "Venezuela",
1179
                "code": "VE"
1180
              },
1181
              {
1182
                "name": "Viet Nam",
1183
                "code": "VN"
1184
              },
1185
              {
1186
                "name": "Virgin Islands, British",
1187
                "code": "VG"
1188
              },
1189
              {
1190
                "name": "Virgin Islands, U.S.",
1191
                "code": "VI"
1192
              },
1193
              {
1194
                "name": "Wallis and Futuna",
1195
                "code": "WF"
1196
              },
1197
              {
1198
                "name": "Western Sahara",
1199
                "code": "EH"
1200
              },
1201
              {
1202
                "name": "Yemen",
1203
                "code": "YE"
1204
              },
1205
              {
1206
                "name": "Zambia",
1207
                "code": "ZM"
1208
              },
1209
              {
1210
                "name": "Zimbabwe",
1211
                "code": "ZW"
1212
              }
1213
            ]
1214
          },
1215
          "valueProperty": "name",
1216
          "template": "<span>{{ item.name }}</span>",
1217
          "validateWhenHidden": false,
1218
          "key": "Country",
1219
          "type": "select",
1220
          "input": true
1221
        },
1222
        {
1223
          "label": "Home Phone",
1224
          "applyMaskOn": "change",
1225
          "tableView": true,
1226
          "validateWhenHidden": false,
1227
          "key": "HomePhone",
1228
          "type": "phoneNumber",
1229
          "input": true
1230
        },
1231
        {
1232
          "label": "Extension",
1233
          "applyMaskOn": "change",
1234
          "mask": false,
1235
          "tableView": false,
1236
          "delimiter": false,
1237
          "requireDecimal": false,
1238
          "inputFormat": "plain",
1239
          "truncateMultipleSpaces": false,
1240
          "validateWhenHidden": false,
1241
          "key": "Extension",
1242
          "type": "number",
1243
          "input": true
1244
        },
1245
        {
1246
          "label": "Notes",
1247
          "applyMaskOn": "change",
1248
          "autoExpand": false,
1249
          "tableView": true,
1250
          "validateWhenHidden": false,
1251
          "key": "Notes",
1252
          "type": "textarea",
1253
          "input": true
1254
        },
1255
        {
1256
          "label": "ReportsTo",
1257
          "optionsLabelPosition": "right",
1258
          "inline": false,
1259
          "tableView": false,
1260
          "values": [
1261
            {
1262
              "label": " Buchanan, Steven",
1263
              "value": " Buchanan, Steven",
1264
              "shortcut": ""
1265
            },
1266
            {
1267
              "label": "Callahan, Laura",
1268
              "value": "Callahan, Laura",
1269
              "shortcut": ""
1270
            },
1271
            {
1272
              "label": "Davolio, Nancy",
1273
              "value": "Davolio, Nancy",
1274
              "shortcut": ""
1275
            },
1276
            {
1277
              "label": "Dodsworth, Anne",
1278
              "value": "Dodsworth, Anne",
1279
              "shortcut": ""
1280
            },
1281
            {
1282
              "label": "Fuller, Andrew",
1283
              "value": "Fuller, Andrew",
1284
              "shortcut": ""
1285
            },
1286
            {
1287
              "label": "King, Robert",
1288
              "value": "King, Robert",
1289
              "shortcut": ""
1290
            },
1291
            {
1292
              "label": "Leverling, Janet",
1293
              "value": "Leverling, Janet",
1294
              "shortcut": ""
1295
            },
1296
            {
1297
              "label": "Peacock, Margaret",
1298
              "value": "Peacock, Margaret",
1299
              "shortcut": ""
1300
            },
1301
            {
1302
              "label": "Suyama, Michael",
1303
              "value": "Suyama, Michael",
1304
              "shortcut": ""
1305
            }
1306
          ],
1307
          "validateWhenHidden": false,
1308
          "key": "ReportsTo",
1309
          "type": "radio",
1310
          "input": true
1311
        }
1312
      ]
1313
    },
1314
    {
1315
      "label": "Save",
1316
      "showValidations": false,
1317
      "disableOnInvalid": true,
1318
      "tableView": false,
1319
      "key": "submit",
1320
      "type": "button",
1321
      "saveOnEnter": false,
1322
      "input": true
1323
    }
1324
  ]
1325
}
1326
```
1327
1328
1329
## HTML Template
1330
1331
``` html
1332
<!DOCTYPE html>
1333
<html lang="en">
1334
1335
<head>
1336
    <meta name="viewport"
1337
        content="user-scalable=no, initial-scale=1.0001, maximum-scale=1.0001, width=device-width, minimal-ui shrink-to-fit=no">
1338
    <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0" />
1339
    <title>Northwind</title>
1340
1341
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
1342
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
1343
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css">
1344
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/awesome-notifications/3.1.0/style.min.css">
1345
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/w2ui@2.0.0/w2ui-2.0.min.css">
1346
    <script src="https://cdnjs.cloudflare.com/ajax/libs/awesome-notifications/3.1.0/modern.var.min.js"></script>
1347
    <script src="https://cdn.jsdelivr.net/npm/localstorage-slim"></script>
1348
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
1349
    <script src="https://cdn.form.io/js/formio.embed.js"></script>
1350
</head>
1351
1352
<body>
1353
    <style>
1354
        button[type="submit"] {
1355
            background-color: #007bff;
1356
            color: white;
1357
            padding: 10px 15px;
1358
            border: none;
1359
            border-radius: 4px;
1360
            cursor: pointer;
1361
            font-size: 1em;
1362
            width: 100%;
1363
        }
1364
    </style>
1365
    <div id="toolbar"></div>
1366
    <div id="formio"></div>
1367
    <script type="module">
1368
        import { w2toolbar } from "https://cdn.jsdelivr.net/npm/w2ui@2.0.0/w2ui-2.0.es6.min.js";
1369
        var $ds = {};
1370
        var email = ls.get("email");
1371
        var notifier = new AWN({ option: "top-right" });
1372
        var sid = ls.get("sid");
1373
1374
        $(function () {
1375
            if (sid) {
1376
                google.script.run
1377
                    .withSuccessHandler(onCheckSidSuccess)
1378
                    .withFailureHandler(onInvalidSid)
1379
                    .checkSid(sid);
1380
            }
1381
            else {
1382
                onInvalidSid();
1383
            }
1384
        });
1385
1386
        function onInvalidSid(err) {
1387
            if (err) {
1388
                notifier.warning(err.message);
1389
            }
1390
            else {
1391
                let url = "<?!= base ?>?url=/form/login&callback=<?!= url ?>";
1392
                notifier.modal(`<b>You need to login to access this page.</b><br><a href="${url}">👉 <b>Login</b></a>`)
1393
            }
1394
        }
1395
1396
        function onCheckSidSuccess(valid) {
1397
            new w2toolbar({
1398
                box: "#toolbar",
1399
                name: "toolbar",
1400
                items: [
1401
                    {
1402
                        type: "menu", id: "sales", icon: "w2ui-icon-info", text: "Sales",
1403
                        items: [
1404
                            { id: "customers", text: "Customers", icon: "fa fa-user" },
1405
                            { id: "orders", text: "Orders", icon: "fa fa-file-text" },
1406
                        ]
1407
                    },
1408
                    { type: "break" },
1409
                    {
1410
                        type: "menu", id: "operations", icon: "w2ui-icon-settings", text: "Operations",
1411
                        items: [
1412
                            { id: "employees", text: "Employees", icon: "fa fa-address-card" },
1413
                            { id: "products", text: "Products", icon: "fa fa-archive" },
1414
                            { id: "categories", text: "Product Categories", icon: "fa fa-sitemap" },
1415
                            { id: "suppliers", text: "Suppliers", icon: "fa fa-user" },
1416
                            { id: "shippers", text: "Shippers", icon: "fa fa-shopping-cart" }
1417
                        ]
1418
                    },
1419
                    { type: "spacer" },
1420
                    {
1421
                        type: "menu", id: "auth", text: email,
1422
                        items: [
1423
                            { text: "Logout", id: "logout", icon: "fa fa-sign-out" }
1424
                        ]
1425
                    }
1426
                ],
1427
                onClick(event) {
1428
                    switch (event.target) {
1429
                        case "sales:customers": {
1430
                            window.open("<?= base ?>?url=/form/customers", "_top");
1431
                            break;
1432
                        }
1433
                        case "sales:orders": {
1434
                            window.open("<?= base ?>?url=/form/orders", "_top");
1435
                            break;
1436
                        }
1437
                        case "operations:employees": {
1438
                            window.open("<?= base ?>?url=/form/employees", "_top");
1439
                            break;
1440
                        }
1441
                        case "operations:products": {
1442
                            window.open("<?= base ?>?url=/form/products", "_top");
1443
                            break;
1444
                        }
1445
                        case "operations:categories": {
1446
                            window.open("<?= base ?>?url=/form/categories", "_top");
1447
                            break;
1448
                        }
1449
                        case "operations:suppliers": {
1450
                            window.open("<?= base ?>?url=/form/suppliers", "_top");
1451
                            break;
1452
                        }
1453
                        case "operations:shippers": {
1454
                            window.open("<?= base ?>?url=/form/shippers", "_top");
1455
                            break;
1456
                        }
1457
                        case "auth:logout": {
1458
                            ls.remove("sid");
1459
                            ls.remove("email");
1460
                            window.open("<?= base ?>?url=/form/login&callback=<?!= url ?>", "_top");
1461
                            break;
1462
                        }
1463
                    }
1464
                }
1465
            });
1466
1467
            if (valid) {
1468
                google.script.run.withSuccessHandler(showForms)
1469
                    .loadDatasources("<?!= datasource ?>");
1470
            } else {
1471
                onInvalidSid();
1472
            }
1473
        }
1474
1475
        function showForms(ds) {
1476
            $ds = ds;
1477
            let rec = <?!= (data) ?>;
1478
            Formio.createForm(document.getElementById("formio"), <?!= template ?>)
1479
                .then(function (form) {
1480
                    // Prevent the submission from going to the form.io server.
1481
                    form.noAlerts = true;
1482
                    form.nosubmit = true;
1483
                    form.submission = rec.Document ? { data: JSON.parse(rec.Document) } : {};
1484
1485
                    // Triggered when they click the submit button.
1486
                    form.on("submit", function (submission) {
1487
                        google.script.run
1488
                            .withFailureHandler((err) => {
1489
                                notifier.warning("Successfully saved.");
1490
                                form.emit("submitError");
1491
                            })
1492
                            .withSuccessHandler((id) => {
1493
                                if (!id) {
1494
                                    form.emit("submitError");
1495
                                    notifier.warning("An error occurred while saving the entry.");
1496
                                }
1497
                                else {
1498
                                    form.emit("submitDone");
1499
                                    <? if (!id) { ?>
1500
                                    form.submission = {};
1501
                                    form.refresh();
1502
                                    <? } ?>
1503
                                    notifier.success("Successfully saved.");
1504
                                }
1505
                            })
1506
                            <? if (id) { ?>
1507
                        .update("<?!= id ?>", "<?!= form.Id ?>", { Document: JSON.stringify(submission.data) }, null, sid)
1508
                                <? } else { ?>
1509
                        .create("<?!= form.Id ?>", { Document: JSON.stringify(submission.data) }, sid);
1510
                        <? } ?>
1511
                    });
1512
                });
1513
        }
1514
    </script>
1515
</body>
1516
1517
</html>
1518
```
1519
1520
## Giải thích Code
1521
1522
Form List Employees sử dụng cácthư viện sau:
1523
- [jQuery](https://jquery.com/) để khởi tạo grid sau khi page load xong.
1524
- [localstorage-slim](https://github.com/digitalfortress-tech/localstorage-slim) để đọc sid & email để bỏ qua bước login nếu trước đó đã login thành công. Trường hợp login không thành công thì sẽ thông báo và điều hướng đến trang login.
1525
- [Notyf](https://carlosroso.com/notyf/) hiển thị thông báo.
1526
- [w2ui](https://w2ui.com/web/home) cung cấp các thành phần UI cơ bản và nâng cao, ví dụ: toolbar và grid, dialog...
1527
- Các thư viện đều được load từ CDN để tối ưu tốc độ, đơn giản hóa HTML Templated. Các bạn cần có kiến thức trong phần yêu cầu để hiểu logic của code JS + templated nhúng trong page. 
1528
- Trong page này gọi đến
1529
  - Hàm backend **checkSid** sid lưu trữ có khớp với giá trị trên server, nếu đúng thì sẽ sử dụng email trả về, còn sai sẽ điều hướng đến trang login
1530
  - Hàm backend **loadDatasources** để tải các dữ liệu tham chiếu phía client, ví dụ danh sách Products
1531 2 Lê Sĩ Quý
  - Hàm backend **create** để lưu form submission dưới dạng document trong database NoSQL
1532
  - Hàm backend **update** để cập nhật record đã tồn tại với record id được truyền vào từ url theo định dạng **form-id/record-id**. Trong trường hợp này record-id chính là column Id của document.
1533 1 Lê Sĩ Quý
1534
## Demo
1535
- Link: https://script.google.com/macros/s/AKfycbwIjB-hULVZdfCtsXFPg4Af_8WoKx2AFf85KMVwnsO_WkeAXW3zarT6vZNFVfwccz1_sA/exec?url=/form/employees
1536
- Account: user@northwind.com
1537
- Password: user