-
Version Number7.29.0 Codesandbox/Expo snackhttps://codesandbox.io/s/happy-merkle-10wkfj?file=/src/App.js Steps to reproduce
Expected behaviourI want to render a dynamic and a large number of forms, then I need watch on some form field change and If I use How can I solve this performance problem when I use What browsers are you seeing the problem on?Chrome Relevant log outputwhen I Code of Conduct
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
You can start optimizing your form by considering the use of uncontrolled Antd Input instead of controlled. It integrates well with the Now, without knowing your actual use-case, there're many different things you can do to optimize the performance of your form. Consider searching though the discussions section of RHF repository for threads like #7611. The main idea is to subscribe to values as deep down the React tree as possible where the information this info is relevant; make use of hooks like P.S. I'm gonna convert this issue to a discussion as it's not a problem with RHF but rather a per use-case optimization discussion |
Beta Was this translation helpful? Give feedback.
-
I don't see the slow performance issue here from this lib perspective. Screen.Recording.2022-03-31.at.8.54.14.am.movthe only performance hit is when re-render the entire ant design inputs component which is not something hook form can improve (.map) part. things you can consider is using virtual inputs: https://react-hook-form.com/advanced-usage#Workingwithvirtualizedlists |
Beta Was this translation helpful? Give feedback.
-
@Moshyfawn have same problem, but don't know how I can tackle this, I debug the code and found the issue with controller causing the render don't know, in my case when I start typing, for the onload event it just render a single input, but when I submit I get error fields in my app, and then if I start typing then every single field re-renders. I don't know what is causing. but I checked with the react here is my code "use client";
import { useFormContext } from "react-hook-form";
import InputMask from "react-input-mask";
import {
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import { format, isAfter, isBefore, isValid, parse } from "date-fns";
import { CalendarIcon } from "lucide-react";
import React, { memo, useEffect, useMemo, useState } from "react";
import AutoSelect from "../ui/autoselect";
import { Calendar } from "../ui/calendar";
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
import { Separator } from "../ui/separator";
interface Props {
formData: any;
dataDictionary: any;
}
type WhenType = "before" | "after" | string | undefined;
interface Validations {
mandatory?: boolean;
min_length?: number;
special_char?: boolean;
read_only?: boolean;
isDigit?: boolean;
display?: boolean;
when?: WhenType;
}
interface Field {
name: string;
label: string;
type: string;
sub_label: string;
validations: Validations;
value: string;
group_elements?: Field[];
options?: string[];
dependent_elements: Field[];
dependent_value: string;
sub_group_elements: Field[];
}
export function VisaForm(props: Props) {
const { formData } = props;
return (
<>
<Card className="overflow-hidden h-full">
<CardHeader className="bg-gray-100">
<CardTitle>
<div className="flex gap-3 items-center">
<div className="text-xl">Visa Form</div>
</div>
</CardTitle>
</CardHeader>
<CardContent className="h-full px-0 ps-2 pb-24">
<ScrollArea className="h-full">
{formData?.map((x: Field, i: number) => {
const name: string = x?.name;
return (
<div className="p-4 " key={i}>
<div className="text-xl mb-2 text-black font-bold">
{x?.label}
</div>
<div className="text-[0.8rem] mb-2 text-slate-400">
{x?.sub_label}
</div>
<hr className="w-1/2" />
<div className="grid grid-cols-3 gap-4 p-2">
{x?.group_elements?.map(
(a: Field, i: number) =>
!!a?.validations?.display && (
<FormRenderer
key={i}
field={a}
ind={i}
parentName={name}
/>
)
)}
</div>
</div>
);
})}
</ScrollArea>
</CardContent>
</Card>
</>
);
}
interface FormRendererProps {
field: Field;
ind: number;
parentName: string;
}
const FormRenderer: React.FC<FormRendererProps> = memo(
({ field, ind, parentName }) => {
// const { type } = field;
field.type = !!!field.validations.display ? "hidden" : field.type;
switch (field?.type) {
case "subGroup":
return <SubGroup field={field} key={ind} parentName={parentName} />;
case "textField":
return <InputField field={field} key={ind} parentName={parentName} />;
case "dropdown":
return (
<DropDownField field={field} key={ind} parentName={parentName} />
);
case "dateControl":
return (
<DatePickerField field={field} key={ind} parentName={parentName} />
);
case "hidden":
return <HiddenField field={field} key={ind} parentName={parentName} />;
default:
return <InputField field={field} key={ind} parentName={parentName} />;
}
}
);
interface SubGroupProps {
field: Field;
children?: React.ReactNode;
parentName?: string;
}
interface FieldRenderProps {
field: Field;
parentName?: string;
}
const SubGroup: React.FC<SubGroupProps> = ({ field, parentName }) => {
const { name, label, sub_group_elements } = field;
const fieldName: string = `${parentName}-${name}`;
// console.log("fieldname", fieldName, sub_group_elements);
return (
<Card className={`overflow-hidden`}>
<CardHeader className=" py-3 bg-slate-100">
<CardTitle className="text-sm">{label}</CardTitle>
{/* <CardDescription>Card Description</CardDescription> */}
</CardHeader>
<Separator />
<CardContent className="grid grid-cols-3 gap-4 px-3 pt-3">
{!!sub_group_elements?.length
? sub_group_elements.map((x: any) =>
x?.map((a: Field, i: number) => (
<FormRenderer field={a} ind={i} parentName={fieldName} />
))
)
: null}
</CardContent>
</Card>
);
};
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
const HiddenField: React.FC<FieldRenderProps> = memo(
({ field, parentName }) => {
const form = useFormContext(); // retrieve all hook methods
const { name, label, validations, value } = field;
const fieldName: string = `${parentName}-${name}`;
return (
<FormField
disabled={!!validations?.read_only}
// disabled={!!validations?.read_only || isLoading}
control={form.control}
name={fieldName}
defaultValue={value}
render={({ field }) => (
<FormItem>
<FormLabel className="ellipsis" title={label}>
{label}
{!!validations?.mandatory && (
<span className="text-red-500">*</span>
)}
</FormLabel>
<FormControl>
<Input type="hidden" placeholder={label} {...field} />
</FormControl>
<FormMessage className="ellipsis" />
</FormItem>
)}
/>
);
}
);
const InputField: React.FC<FieldRenderProps> = memo(({ field, parentName }) => {
const form = useFormContext(); // retrieve all hook methods
const { name, label, validations, value, type } = field;
const fieldName: string = `${parentName}-${name}`;
const isDigit = (value: string) => {
const digitRegex = /^\d+$/;
return digitRegex.test(value) || "Only numbers are allowed";
};
const getValidationRules = ({
label,
type,
validations,
}: {
label: string;
type: string;
validations: {
read_only?: boolean;
mandatory?: boolean;
min_length?: number;
isDigit?: (value: string) => boolean | string;
};
}) => {
const baseRules = {
required: !!validations?.mandatory && `${label} is required`,
minLength: validations?.min_length
? {
value: validations.min_length,
message: `${label} must be at least ${validations.min_length} characters long`,
}
: undefined,
validate: validations?.isDigit ? isDigit : undefined,
};
if (label === "Email" || type === "email") {
// @ts-expect-error
baseRules.pattern = {
value: emailPattern,
message: `${label} must be a valid email address`,
};
}
return baseRules;
};
// @ts-expect-error
const validationRules = getValidationRules({ label, type, validations });
return (
<FormField
// disabled={!!validations?.read_only || isLoading}
disabled={!!validations?.read_only}
rules={validationRules}
control={form.control}
name={fieldName}
defaultValue={value}
render={({
field,
fieldState: { isValidating },
formState: { isSubmitting },
}) => (
<FormItem>
<FormLabel className="ellipsis" title={label}>
{label}
{!!validations?.mandatory && (
<span className="text-red-500">*</span>
)}
</FormLabel>
<FormControl>
<Input
placeholder={label}
{...field}
disabled={field.disabled || isSubmitting || isValidating}
/>
</FormControl>
<FormMessage className="ellipsis" />
</FormItem>
)}
/>
);
});
const DropDownField: React.FC<FieldRenderProps> = memo(
({ field, parentName }) => {
const [menuPortalTarget, setMenuPortalTarget] =
useState<null | HTMLElement>(null);
const form = useFormContext(); // retrieve all hook methods
const {
name,
label,
validations,
value,
options,
dependent_elements = [],
} = field;
const fieldName: string = `${parentName}-${name}`;
let getStateValue = useMemo(
() => form.watch(fieldName),
[form.watch(fieldName)]
);
const dependantElements = useMemo(
() =>
dependent_elements.filter((a) => a?.dependent_value === getStateValue),
[getStateValue]
);
useEffect(() => {
if (typeof document !== "undefined") {
setMenuPortalTarget(document.querySelector("body"));
}
}, []);
let renderOpt = options?.map((x: string) => ({
label: x,
value: x,
}));
return (
<>
<div
className={
!!dependent_elements?.length
? "col-span-12 grid grid-cols-3 gap-4 p-2"
: ""
}
>
<FormField
control={form.control}
name={fieldName}
// disabled={!!validations?.read_only || isLoading}
disabled={!!validations?.read_only}
rules={{
required: !!validations?.mandatory && label + " is required",
minLength: validations?.min_length,
}}
defaultValue={value && value}
render={({
field: { value, onChange, onBlur, ...rest },
fieldState: { isValidating, invalid },
formState: { isSubmitting },
}) => (
<FormItem>
<FormLabel className="ellipsis" title={label}>
{label}
{!!validations?.mandatory && (
<span className="text-red-500">*</span>
)}
</FormLabel>
<AutoSelect
options={renderOpt}
className={!!invalid ? "[&>div]:bg-red-500/20" : ""}
menuPosition="fixed"
onBlur={onBlur}
placeholder="Select an option"
menuPortalTarget={menuPortalTarget}
menuShouldBlockScroll
isDisabled={rest.disabled || isSubmitting || isValidating}
{...rest}
defaultValue={value && { label: value, value: value }}
onChange={(val: any) => {
onChange(val?.value);
form.setValue(fieldName, val?.value);
}}
/>
<FormMessage className="ellipsis" />
</FormItem>
)}
/>
</div>
{!!dependantElements?.length && (
<div className="col-span-12">
{dependantElements?.map((a: Field, i: number) => (
<FormRenderer field={a} ind={i} parentName={fieldName} />
))}
</div>
)}
</>
);
}
);
// Date picker
const DatePickerField: React.FC<FieldRenderProps> = memo(
({ field, parentName }) => {
const [selectedDate, setSelectedDate] = useState<string | null>(null);
const [isOpen, setIsOpen] = useState<boolean>(false);
const form = useFormContext(); // retrieve all hook methods
const { name, label, validations, value } = field;
const fieldName = `${parentName}-${name}`;
const checkMinMaxDate: WhenType = validations?.when || "before"; // Providing a default value of 'before' if validations?.when is undefined
// Define validation function for validDate
const validDate = (date: string) => {
const parsedDate = parse(date, "dd-MM-yyyy", new Date());
return (
isValid(parsedDate) || "Please enter a valid date in dd-mm-yyyy format"
);
};
// Define validation function for minDate
const minDate = (date: string) => {
const today = new Date();
const selectedParsedDate = parse(date, "dd-MM-yyyy", new Date());
return (
isBefore(selectedParsedDate, today) ||
`Date must be before today's date`
);
};
// Define validation function for maxDate
const maxDate = (date: string) => {
const today = new Date();
const selectedParsedDate = parse(date, "dd-MM-yyyy", new Date());
return (
isAfter(selectedParsedDate, today) || `Date must be after today's date`
);
};
const calculateDateRange = (checkMinMaxDate: WhenType) => {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
let fromDate, toDate;
if (checkMinMaxDate === "after") {
fromDate = new Date(
currentYear,
currentDate.getMonth(),
currentDate.getDate()
);
toDate = new Date(
currentYear + 100,
currentDate.getMonth(),
currentDate.getDate()
);
} else if (checkMinMaxDate === "before") {
fromDate = new Date(
currentYear - 100,
currentDate.getMonth(),
currentDate.getDate()
);
toDate = new Date(
currentYear,
currentDate.getMonth(),
currentDate.getDate()
);
} else {
// Default range: 100 years centered around the current date
fromDate = new Date(
currentYear - 50,
currentDate.getMonth(),
currentDate.getDate()
);
toDate = new Date(
currentYear + 50,
currentDate.getMonth(),
currentDate.getDate()
);
}
return { fromDate, toDate };
};
const getParsedDate = (value: string) =>
new Date(value.split("-").reverse().join("-")).toISOString();
useEffect(() => {
if (!value) return;
let parsedDate = getParsedDate(value);
setSelectedDate(parsedDate);
}, [value]);
return (
<>
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<FormField
disabled={validations?.read_only}
rules={{
required: !!validations?.mandatory && label + " is required",
validate: {
validDate,
...(checkMinMaxDate === "before" && { minDate }),
...(checkMinMaxDate === "after" && { maxDate }),
},
}}
control={form.control}
name={fieldName}
defaultValue={value ?? ""}
render={({
field: { onChange, value, ref, ...args },
fieldState: { invalid, isValidating },
formState: { isSubmitting },
}) => (
<FormItem>
<FormLabel className="ellipsis" title={label}>
{label}
{!!validations?.mandatory && (
<span className="text-red-500">*</span>
)}
</FormLabel>
<FormControl>
<>
<InputMask
mask="99-99-9999"
disabled={args.disabled || isValidating || isSubmitting}
onChange={(e) => {
onChange(e);
let inputValue = e.target.value;
const parsedDate = parse(
inputValue,
"dd-MM-yyyy",
new Date()
);
// Check if the parsed date is valid
if (isValid(parsedDate)) {
setSelectedDate(parsedDate as unknown as string); // Update the selectedDate state with the parsed date
}
}}
value={value}
className="relative"
{...args}
>
{/* @ts-expect-error */}
{(inputProps: HTMLInputElement) => (
<div className="relative">
{/* @ts-expect-error */}
<Input
{...inputProps}
ref={ref}
placeholder={label}
className={invalid ? "bg-red-500/20" : ""}
/>
<CalendarIcon
onClick={() => setIsOpen(true)}
className="absolute right-3 z-[1] cursor-pointer translate-y-[-50%] top-[50%] h-4 w-4 opacity-50"
/>
</div>
)}
</InputMask>
</>
</FormControl>
<FormMessage className="ellipsis" />
</FormItem>
)}
/>
{/* <Button variant="outline">Edit Profile</Button> */}
<DialogContent className="max-w-[300px]">
<DialogHeader>
<DialogTitle>
Select a {label}
{!!validations?.mandatory && (
<span className="text-red-500">*</span>
)}
</DialogTitle>
<DialogDescription>
Please select a {label} as per your document.
</DialogDescription>
</DialogHeader>
<div className="flex justify-center -mx-6">
<Calendar
defaultMonth={
selectedDate ? new Date(selectedDate as string) : new Date()
}
captionLayout="dropdown-buttons"
{...calculateDateRange(checkMinMaxDate)}
mode="single"
// @ts-ignore
selected={new Date(selectedDate)}
onSelect={(date: any) => {
if (!date) return;
// @ts-ignore
let val = format(date, "dd-MM-yyyy");
form.setValue(fieldName, val, {
shouldDirty: true,
shouldTouch: true,
shouldValidate: true,
});
setSelectedDate(date);
setIsOpen(false);
}}
className="rounded-md border"
/>
</div>
</DialogContent>
</Dialog>
</>
);
}
); and here is the json form data [
{
"name": "contact_information",
"label": "Contact Information",
"sub_label": "Current contact details for effective communication during the visa processing period.",
"type": "group",
"group_elements": [
{
"name": "applicants_telephone",
"label": "Phone Number",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": true,
"min_length": 2,
"special_char": false,
"read_only": false,
"isDigit": true,
"display": true
},
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "applicants_email",
"label": "Email",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": true,
"min_length": 2,
"special_char": false,
"read_only": false,
"isDigit": false,
"display": true
},
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "address_line1",
"label": "Home Address (If you don't find your street address, please enter your neighborhood, city and country)",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": true,
"min_length": 2,
"special_char": false,
"read_only": false,
"isDigit": false,
"display": true
},
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "occupation",
"label": "Occupation",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"Accountant",
"Actuary",
"Administrator",
"Agricultural",
"Agriculturer",
"Air traffic pilots",
"Air traffic safety electronics technicians",
"Aircraft engine mechanics",
"Application Programmer",
"Architect",
"Artist",
"Assistant professor",
"Auditor",
"Authors",
"Bank Agent",
"Banker",
"Beautician",
"Biologist",
"Business Person",
"Cartographer",
"Cashier",
"Ceramics Technologist",
"Chef",
"Chemical Engineer",
"Chemical processing plant controller",
"Chemist",
"Chief Accountant",
"Chief Financial Officer",
"Civil Engineer",
"Civil Registration Officer",
"Civil servant",
"Clerk",
"Commercial Manager",
"Computer Scientist",
"Consultant",
"Contractor",
"Criminal Analyst",
"Criminal Record Officer",
"Customs Agencies",
"Dentist",
"Designer",
"Diplomat",
"Domestic Worker",
"Driver",
"Ecologist",
"Education Manager",
"Education Methods Specialist",
"Electrician",
"Electronics Engineer",
"Embassy Agent",
"Engineer",
"Environmental Engineer",
"Evangelist",
"Film",
"Food and beverage tasters and graders",
"Food Scientist",
"Football Coach",
"Geologist and Geophysicist",
"Glass Technologist",
"Health Adviser",
"Historian",
"Hospital (Medical) Administrator",
"Hotel Manager",
"Humanitarian Agent",
"Hydrometeorologist",
"Incinerator and water treatment",
"Industrial and Production Engineer",
"Information Technology Trainer",
"Interior designer",
"Jewelry precious metal worker",
"Journalist/Reporter",
"Judge",
"Landscape architects",
"Lawyer",
"Lecturer",
"Legal Advisor",
"Life science technician",
"Logistician",
"Manufacturing Manager",
"Mathematician",
"Mechanic",
"Mechanical Machinery Assembler",
"Medical and Pathology Laboratory Technician",
"Medical Doctor",
"Medical imaging and therapeutic equipment tech",
"Medical Practitioner",
"Member Of Parliament",
"Metal production process controllers",
"Midwifery Professional",
"Military",
"Mining",
"Missionary",
"Museum and library technicians",
"Notary",
"Nurse",
"Nutritionist",
"Optometrists and ophthalmic opticians",
"Pastor",
"Petroleum and natural gas refining plant op",
"Pharmacist",
"Physicist",
"Physiotherapist",
"Pilot",
"Plumber",
"Policeman/woman",
"Politician",
"Priest",
"Procurement Officer",
"Professor",
"Power production plant operator",
"Professional player",
"Product and garment designers",
"Professionally Qualified TVET Trainer",
"Psychologist",
"Public Prosecution Officer",
"Religious leader",
"Researcher",
"Retired",
"Secretary",
"Securities and finance dealers",
"Sheet Metal Worker",
"Ship's engineer",
"Sociologist",
"Sports coaches and instructors",
"Statistician",
"Student",
"System analysts (IT)",
"Tax Expert/Fiscalist",
"Technical Production Director",
"Technician",
"Toolmaker and Related Worker",
"Trader",
"Tradeswoman",
"Traffic Planner",
"Translator",
"Underwater divers",
"UN Official",
"Unemployed",
"Values and Loss Assessors",
"Veterinarian",
"Wood processing and finishing",
"Other"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false
},
{
"name": "emergency_fullname",
"label": "Emergency Full Name Contact",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": false,
"min_length": 2,
"special_char": false,
"read_only": false,
"isDigit": true,
"display": true
},
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "phone_number",
"label": "Phone Number",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": false,
"min_length": 2,
"special_char": false,
"read_only": false,
"isDigit": true,
"display": true
},
"value": "",
"ocr_field": true,
"oneTimeUse": false
}
]
},
{
"name": "trip_information",
"label": "Trip Information",
"sub_label": "Details of Trip Information, for a smooth visa approval process.",
"type": "group",
"group_elements": [
{
"name": "reason_of_travel",
"label": "Reason of travel",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"TOURISM"
],
"value": "TOURISM",
"ocr_field": true,
"oneTimeUse": true
},
{
"name": "date_of_arrival",
"label": "Arrival Date",
"type": "dateControl",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"format": "dd-MM-yyyy",
"display": true,
"when": "after"
},
"value": "",
"ocr_field": true,
"oneTimeUse": true
},
{
"name": "select_arrival_airport",
"label": "Select arrival airport in Kenya",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"Eldoret International Airport (Nakuru)",
"Isiolo Airport (Isiolo)",
"Kisumu Airport (Kisumu)",
"Lokichoggio Airport (Lokichoggio)",
"Malindi Airport (Mombasa)",
"Wilson Airport (Nairobi)",
"Wajir Airport (Wajir)"
],
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "arrival_airline",
"label": "Arrival Airline",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"Kenya Airways",
"Emirates",
"African Express Airways",
"Air Arabia",
"Air France",
"Airkenya Express",
"Airlink",
"Astral Aviation",
"British Airways",
"Charter or Other Airline",
"China Southern Airlines",
"Condor",
"Discover Airlines",
"EgyptAir",
"Emirates",
"Ethiopian Airlines",
"FlexFlight",
"Freedom Airline Express",
"IndiGo",
"Jubba Airways",
"KLM",
"Kenya Airways",
"Land Border",
"Lot",
"Lufthansa",
"Martinair Holland",
"Neos",
"Precision Air",
"Private Jet",
"Qatar Airways",
"RwandAir",
"Safarilink Aviation",
"Saudia",
"Swiss International Air Lines",
"Taquan Air",
"Turkish Airlines",
"Uganda Airlines"
],
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "arrival_flight_number",
"label": "Arrival Flight Number",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": true,
"min_length": 2,
"special_char": false,
"read_only": false,
"isDigit": false,
"display": true
},
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "country_of_origin_for_your_trip",
"label": "Select the country of origin for your trip",
"type": "dropdown",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"AFGHANISTAN",
"ALBANIA",
"ALGERIA",
"ANDORRA",
"ANGOLA",
"ANTIGUA & BARBUDA",
"ARGENTINA",
"ARMENIA",
"AUSTRALIA",
"AUSTRIA",
"AZERBAIJAN",
"BAHAMAS",
"BAHRAIN",
"BANGLADESH",
"BARBADOS",
"BELGIUM",
"BELIZE",
"BENIN",
"BERMUDA",
"BHUTAN",
"BOLIVIA",
"BOSNIA AND HERZEG",
"BOTSWANA",
"BRAZIL",
"BRITAIN",
"BRUNEI",
"BULGARIA",
"BURKINA FASO",
"BURMA UNION MYANMAR",
"BURUNDI",
"CABO VERDE",
"CAMBODIA",
"CAMEROON",
"CANADA",
"CENTRAL AFRICA REP",
"CHAD",
"CHILE",
"CHINA",
"COLOMBIA",
"COMONWEALTH DOMINICA",
"COMOROS",
"CONGO",
"COSTARICA",
"CROATIA",
"CUBA",
"CYPRUS",
"CZECH",
"DAGHYSTAN",
"DAHOOMI",
"DEMOCRATIC REPUBLIC OF THE CONGO",
"DENMARK",
"DJIBOUTI",
"DOMINICAN",
"ECUADOR",
"EGYPT",
"EL SALVADOR",
"EMIRATES",
"ENTIAGO",
"Equatorial Guinea",
"ERITREN",
"ESTONIA",
"ETHIOPIA",
"Faroese",
"FIJI",
"FINLAND",
"FRANCE",
"FRENCH GUIANA",
"GABON",
"GAMBIA",
"GEORGIA",
"GERMANY",
"GHANA",
"GHINIA BISSAU",
"GREECE",
"GREENLAND",
"GRENADA",
"GUATAMALA",
"GUYANA",
"HAITI",
"HOLLAND",
"HONDURAS",
"HONG KONG",
"HUNGARY",
"ICELAND",
"INDIA",
"INDONESIA",
"INT",
"IRAN",
"IRAQ",
"IRELAND",
"ISRAEL",
"ITALY",
"IVORY COAST",
"JAMAICA",
"JAPAN",
"JORDAN",
"KAIMAN ISLAN",
"KALDUNIA NEW",
"KAZAKHESTAN",
"KENYA",
"KINGSTONE",
"KIRIBATI",
"KOSOVA",
"KURDISH",
"KUWAIT",
"Kyrgyzstani",
"LAOS",
"LATVIA",
"LATVIA RES",
"LEBANON",
"LESOTHO",
"LIBERIA",
"LIBYA",
"LIECHTENSTEIN",
"LITHUANIA",
"LUXEMBOURG",
"MACAU",
"MADAGASCAR",
"MALAWI",
"MALAYSIA",
"MALDIVES",
"MALI",
"MALTA",
"MARSHALL ISLAND",
"MARTINIQUE",
"MARYANA ISLAND",
"MAURITANIA",
"MAURITIUS",
"MEXICO",
"MICRONESIA",
"MOLDAVIA",
"MONACO",
"MONGOLIA",
"MONTENEGRO",
"MOROCCO",
"MOZAMBIQUE",
"NAMIBIA",
"NAURU",
"NEPAL",
"NEW GHINIA",
"NEW ZEALAND",
"NICARAGUA",
"NIGER",
"NIGERIA",
"NORTH KOREA",
"NORWAY",
"PAKISTAN",
"PALAU",
"PALESTINE",
"PANAMA",
"PAPUA NEW GUINEA",
"PARAGUAY",
"PERU",
"PHILIPPINES",
"POLAND",
"PORTUGAL",
"PUERTO RICO",
"QATAR",
"REPUBLIC OF MACEDONIA",
"REPUBLIC OF BELARUS",
"REPUBLIC OF SOMALILAND",
"REPUPLIC OF GUINEA",
"ROMANIA",
"RWANDA",
"RUSSIA",
"SAINT LUCIA",
"SAINT VINSENT",
"SAN MARINO",
"SAO TOME",
"SAUDI ARABIA",
"SENEGAL",
"SICHEL",
"SIERRA LEONE",
"SINGAPORE",
"SLOVAKIA",
"SLOVENIA",
"SOLOMON ISLAND",
"SOMALIA",
"SOUTH AFRICA",
"SOUTH KOREA",
"SOUTH SUDAN",
"SPAIN",
"SRI LANKA",
"ST CHRISTOPHER",
"ST HELENA",
"ST KITTS-NAVIS",
"SUDAN",
"SULTANATE OF OMAN",
"SURBIA",
"SURINAME",
"SWAZILAND",
"SWEDEN",
"SWIZERLAND",
"SYRIA",
"TAHITI",
"TAIWAN",
"TAJIKISTAN",
"TANZANIA",
"TASMANIA",
"THAILAND",
"TIMOR LESTE",
"TOGO",
"TONGA",
"TRINIDAD",
"TUNISIA",
"TURKEY",
"TURKMENISTAN",
"TUVALU",
"UNITED STATES OF AMERICA",
"UGANDA",
"UKRAINE",
"United Nations",
"URGWAY",
"UZBAKISTAN",
"VANUATU",
"VATICAN",
"VENEZUELA",
"VIETNAM",
"W SAMOA",
"YEMEN",
"YUGOSLAVIA",
"ZAMBIA",
"ZIMBABWE"
],
"value": "",
"ocr_field": true,
"oneTimeUse": true
},
{
"name": "date_of_departure",
"label": "Departure Date",
"type": "dateControl",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"format": "dd-MM-yyyy",
"display": true,
"when": "after"
},
"value": "",
"ocr_field": true,
"oneTimeUse": true
},
{
"name": "select_depature_airport",
"label": "Departure Airport in Kenya",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"Eldoret International Airport (Nakuru)",
"Isiolo Airport (Isiolo)",
"Kisumu Airport (Kisumu)",
"Lokichoggio Airport (Lokichoggio)",
"Malindi Airport (Mombasa)",
"Wilson Airport (Nairobi)",
"Wajir Airport (Wajir)"
],
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "departure_airline",
"label": "Departure Airline",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"Kenya Airways",
"Emirates",
"African Express Airways",
"Air Arabia",
"Air France",
"Airkenya Express",
"Airlink",
"Astral Aviation",
"British Airways",
"Charter or Other Airline",
"China Southern Airlines",
"Condor",
"Discover Airlines",
"EgyptAir",
"Emirates",
"Ethiopian Airlines",
"FlexFlight",
"Freedom Airline Express",
"IndiGo",
"Jubba Airways",
"KLM",
"Kenya Airways",
"Land Border",
"Lot",
"Lufthansa",
"Martinair Holland",
"Neos",
"Precision Air",
"Private Jet",
"Qatar Airways",
"RwandAir",
"Safarilink Aviation",
"Saudia",
"Swiss International Air Lines",
"Taquan Air",
"Turkish Airlines",
"Uganda Airlines"
],
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "final_destination_country",
"label": "Destination Country",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": false,
"read_only": false,
"display": true
},
"options": [
"Afghanistan",
"African Union",
"Albania",
"Algeria",
"American Samoa",
"Andorra",
"Angola",
"Anguilla",
"Antigua and Barbuda",
"Argentina",
"Armenia",
"Aruba",
"Ashmore and Cartier Islands",
"Australia",
"Austria",
"Azerbaijan",
"Bahamas",
"Bahrain",
"Bangladesh",
"Barbados",
"Belarus",
"Belgium",
"Belize",
"Benin",
"Bermuda",
"Bhutan",
"Bolivia",
"Bosnia and Herzegovina",
"Botswana",
"Brazil",
"Brunei",
"Bulgaria",
"Burkina Faso",
"Burma",
"Burundi",
"Cambodia",
"Cameroon",
"Canada",
"Cape Verde",
"Cayman Islands",
"Central African Republic",
"Chad",
"Chile",
"China",
"Cocos (Keeling) Islands",
"Colombia",
"COMESA",
"Comoros",
"Congo Brazzaville",
"Cook Islands",
"Costa Rica",
"Cote dIvoire",
"Croatia",
"Cuba",
"Cyprus",
"Czech Republic",
"Denmark",
"DEUTSCHLAND",
"Djibouti",
"Dominica",
"Dominican Republic",
"DR Congo",
"Ecuador",
"Egypt",
"El Salvador",
"Equatorial Guinea",
"Eritrea",
"Estonia",
"Ethiopia",
"Falkland Islands (Islas Malvinas)",
"Faroe Islands",
"Fiji",
"Finland",
"France",
"French Guiana",
"French Polynesia",
"French West Indies",
"Gabon",
"Gambia",
"Georgia",
"Ghana",
"Gibraltar",
"Greece",
"Greenland",
"Grenada",
"Guadeloupe",
"Guam",
"Guatemala",
"Guinea",
"Guinea Conakry",
"Guinea-Bissau",
"Guyana",
"Haiti",
"Holy See (Vatican City)",
"Honduras",
"Hungary",
"Iceland",
"India",
"Indonesia",
"Iran",
"Iraq",
"Ireland",
"Israel",
"Italy",
"Jamaica",
"Japan",
"Jordan",
"Kazakstan",
"Kenya",
"Kingdom of Eswatini",
"Kiribati",
"Korea",
"North - PRK",
"Korea",
"South",
"Kuwait",
"Kyrgyzstan",
"Laos",
"Latvia",
"Lebanon",
"Lesotho",
"Liberia",
"Libya",
"Liechtenstein",
"Lithuania",
"Luxembourg",
"Macau",
"Macedonia",
"Madagascar",
"Malawi",
"Malaysia",
"Maldives",
"Mali",
"Malta",
"Mauritania",
"Mauritius",
"Mexico",
"Moldova",
"Monaco",
"Mongolia",
"Montenegro",
"Morocco",
"Mozambique",
"Myanmar",
"Namibia",
"Nauru",
"Nepal",
"Netherlands",
"New Caledonia",
"New Zealand",
"Nicaragua",
"Niger",
"Nigeria",
"Norway",
"Oman",
"Pakistan",
"Palau",
"Palestine Territories",
"Panama",
"Papua New Guinea",
"Paraguay",
"Peru",
"Philippines",
"Poland",
"Portugal",
"Puerto Rico",
"Qatar",
"Romania",
"Russia",
"Rwanda",
"Saint Kitts and Nevis",
"Saint Lucia",
"Samoa",
"San Marino",
"Sao Tome and Prince",
"Saudi Arabia",
"Senegal",
"Serbia",
"Seychelles",
"Sierra Leone",
"Singapore",
"Slovakia",
"Slovenia",
"Somalia",
"South Africa",
"SOUTH SUDAN",
"Spain",
"Sri Lanka",
"Sudan",
"Suriname",
"Sweden",
"Switzerland",
"Syria",
"Taiwan",
"Tajikistan",
"Tanzania",
"Thailand",
"Timor-Leste",
"Togo",
"Tonga",
"Trinidad and Tobago",
"Tunisia",
"Turkey",
"Turkmenistan",
"Uganda",
"Ukraine",
"United Arab Emirates",
"United Kingdom",
"United States of America",
"Uruguay",
"Utopia",
"Uzbekistan",
"Vanuatu",
"Venezuela",
"Vietnam",
"Virgin Islands",
"Yemen",
"Zambia",
"Zimbabwe"
],
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "where_are_you_staying_in_kenya",
"label": "Where are you staying in Kenya?",
"type": "textField",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"value": "",
"ocr_field": false,
"oneTimeUse": true
},
{
"name": "date_from",
"label": "From Date",
"type": "dateControl",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"format": "dd-MM-yyyy",
"display": true,
"when": "after"
},
"value": "",
"ocr_field": true,
"oneTimeUse": true
},
{
"name": "to_date",
"label": "To Date",
"type": "dateControl",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"format": "dd-MM-yyyy",
"display": true,
"when": "after"
},
"value": "",
"ocr_field": true,
"oneTimeUse": true
}
]
},
{
"name": "general_information",
"label": "General Information",
"sub_label": "General Information required for identification purposes in the visa application.",
"type": "group",
"group_elements": [
{
"name": "birth_country",
"label": "Country of Birth",
"type": "dropdown",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"AFGHANISTAN",
"ALBANIA",
"ALGERIA",
"ANDORRA",
"ANGOLA",
"ANTIGUA & BARBUDA",
"ARGENTINA",
"ARMENIA",
"AUSTRALIA",
"AUSTRIA",
"AZERBAIJAN",
"BAHAMAS",
"BAHRAIN",
"BANGLADESH",
"BARBADOS",
"BELGIUM",
"BELIZE",
"BENIN",
"BERMUDA",
"BHUTAN",
"BOLIVIA",
"BOSNIA AND HERZEG",
"BOTSWANA",
"BRAZIL",
"BRITAIN",
"BRUNEI",
"BULGARIA",
"BURKINA FASO",
"BURMA UNION MYANMAR",
"BURUNDI",
"CABO VERDE",
"CAMBODIA",
"CAMEROON",
"CANADA",
"CENTRAL AFRICA REP",
"CHAD",
"CHILE",
"CHINA",
"COLOMBIA",
"COMONWEALTH DOMINICA",
"COMOROS",
"CONGO",
"COSTARICA",
"CROATIA",
"CUBA",
"CYPRUS",
"CZECH",
"DAGHYSTAN",
"DAHOOMI",
"DEMOCRATIC REPUBLIC OF THE CONGO",
"DENMARK",
"DJIBOUTI",
"DOMINICAN",
"ECUADOR",
"EGYPT",
"EL SALVADOR",
"EMIRATES",
"ENTIAGO",
"Equatorial Guinea",
"ERITREN",
"ESTONIA",
"ETHIOPIA",
"Faroese",
"FIJI",
"FINLAND",
"FRANCE",
"FRENCH GUIANA",
"GABON",
"GAMBIA",
"GEORGIA",
"GERMANY",
"GHANA",
"GHINIA BISSAU",
"GREECE",
"GREENLAND",
"GRENADA",
"GUATAMALA",
"GUYANA",
"HAITI",
"HOLLAND",
"HONDURAS",
"HONG KONG",
"HUNGARY",
"ICELAND",
"INDIA",
"INDONESIA",
"INT",
"IRAN",
"IRAQ",
"IRELAND",
"ISRAEL",
"ITALY",
"IVORY COAST",
"JAMAICA",
"JAPAN",
"JORDAN",
"KAIMAN ISLAN",
"KALDUNIA NEW",
"KAZAKHESTAN",
"KENYA",
"KINGSTONE",
"KIRIBATI",
"KOSOVA",
"KURDISH",
"KUWAIT",
"Kyrgyzstani",
"LAOS",
"LATVIA",
"LATVIA RES",
"LEBANON",
"LESOTHO",
"LIBERIA",
"LIBYA",
"LIECHTENSTEIN",
"LITHUANIA",
"LUXEMBOURG",
"MACAU",
"MADAGASCAR",
"MALAWI",
"MALAYSIA",
"MALDIVES",
"MALI",
"MALTA",
"MARSHALL ISLAND",
"MARTINIQUE",
"MARYANA ISLAND",
"MAURITANIA",
"MAURITIUS",
"MEXICO",
"MICRONESIA",
"MOLDAVIA",
"MONACO",
"MONGOLIA",
"MONTENEGRO",
"MOROCCO",
"MOZAMBIQUE",
"NAMIBIA",
"NAURU",
"NEPAL",
"NEW GHINIA",
"NEW ZEALAND",
"NICARAGUA",
"NIGER",
"NIGERIA",
"NORTH KOREA",
"NORWAY",
"PAKISTAN",
"PALAU",
"PALESTINE",
"PANAMA",
"PAPUA NEW GUINEA",
"PARAGUAY",
"PERU",
"PHILIPPINES",
"POLAND",
"PORTUGAL",
"PUERTO RICO",
"QATAR",
"REPUBLIC OF MACEDONIA",
"REPUBLIC OF BELARUS",
"REPUBLIC OF SOMALILAND",
"REPUPLIC OF GUINEA",
"ROMANIA",
"RWANDA",
"RUSSIA",
"SAINT LUCIA",
"SAINT VINSENT",
"SAN MARINO",
"SAO TOME",
"SAUDI ARABIA",
"SENEGAL",
"SICHEL",
"SIERRA LEONE",
"SINGAPORE",
"SLOVAKIA",
"SLOVENIA",
"SOLOMON ISLAND",
"SOMALIA",
"SOUTH AFRICA",
"SOUTH KOREA",
"SOUTH SUDAN",
"SPAIN",
"SRI LANKA",
"ST CHRISTOPHER",
"ST HELENA",
"ST KITTS-NAVIS",
"SUDAN",
"SULTANATE OF OMAN",
"SURBIA",
"SURINAME",
"SWAZILAND",
"SWEDEN",
"SWIZERLAND",
"SYRIA",
"TAHITI",
"TAIWAN",
"TAJIKISTAN",
"TANZANIA",
"TASMANIA",
"THAILAND",
"TIMOR LESTE",
"TOGO",
"TONGA",
"TRINIDAD",
"TUNISIA",
"TURKEY",
"TURKMENISTAN",
"TUVALU",
"UNITED STATES OF AMERICA",
"UGANDA",
"UKRAINE",
"United Nations",
"URGWAY",
"UZBAKISTAN",
"VANUATU",
"VATICAN",
"VENEZUELA",
"VIETNAM",
"W SAMOA",
"YEMEN",
"YUGOSLAVIA",
"ZAMBIA",
"ZIMBABWE"
],
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "nationality_at_birth",
"label": "Nationality At Birth",
"type": "dropdown",
"is_important": true,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"AFGHANISTAN",
"ALBANIA",
"ALGERIA",
"ANDORRA",
"ANGOLA",
"ANTIGUA & BARBUDA",
"ARGENTINA",
"ARMENIA",
"AUSTRALIA",
"AUSTRIA",
"AZERBAIJAN",
"BAHAMAS",
"BAHRAIN",
"BANGLADESH",
"BARBADOS",
"BELGIUM",
"BELIZE",
"BENIN",
"BERMUDA",
"BHUTAN",
"BOLIVIA",
"BOSNIA AND HERZEG",
"BOTSWANA",
"BRAZIL",
"BRITAIN",
"BRUNEI",
"BULGARIA",
"BURKINA FASO",
"BURMA UNION MYANMAR",
"BURUNDI",
"CABO VERDE",
"CAMBODIA",
"CAMEROON",
"CANADA",
"CENTRAL AFRICA REP",
"CHAD",
"CHILE",
"CHINA",
"COLOMBIA",
"COMONWEALTH DOMINICA",
"COMOROS",
"CONGO",
"COSTARICA",
"CROATIA",
"CUBA",
"CYPRUS",
"CZECH",
"DAGHYSTAN",
"DAHOOMI",
"DEMOCRATIC REPUBLIC OF THE CONGO",
"DENMARK",
"DJIBOUTI",
"DOMINICAN",
"ECUADOR",
"EGYPT",
"EL SALVADOR",
"EMIRATES",
"ENTIAGO",
"Equatorial Guinea",
"ERITREN",
"ESTONIA",
"ETHIOPIA",
"Faroese",
"FIJI",
"FINLAND",
"FRANCE",
"FRENCH GUIANA",
"GABON",
"GAMBIA",
"GEORGIA",
"GERMANY",
"GHANA",
"GHINIA BISSAU",
"GREECE",
"GREENLAND",
"GRENADA",
"GUATAMALA",
"GUYANA",
"HAITI",
"HOLLAND",
"HONDURAS",
"HONG KONG",
"HUNGARY",
"ICELAND",
"INDIA",
"INDONESIA",
"INT",
"IRAN",
"IRAQ",
"IRELAND",
"ISRAEL",
"ITALY",
"IVORY COAST",
"JAMAICA",
"JAPAN",
"JORDAN",
"KAIMAN ISLAN",
"KALDUNIA NEW",
"KAZAKHESTAN",
"KENYA",
"KINGSTONE",
"KIRIBATI",
"KOSOVA",
"KURDISH",
"KUWAIT",
"Kyrgyzstani",
"LAOS",
"LATVIA",
"LATVIA RES",
"LEBANON",
"LESOTHO",
"LIBERIA",
"LIBYA",
"LIECHTENSTEIN",
"LITHUANIA",
"LUXEMBOURG",
"MACAU",
"MADAGASCAR",
"MALAWI",
"MALAYSIA",
"MALDIVES",
"MALI",
"MALTA",
"MARSHALL ISLAND",
"MARTINIQUE",
"MARYANA ISLAND",
"MAURITANIA",
"MAURITIUS",
"MEXICO",
"MICRONESIA",
"MOLDAVIA",
"MONACO",
"MONGOLIA",
"MONTENEGRO",
"MOROCCO",
"MOZAMBIQUE",
"NAMIBIA",
"NAURU",
"NEPAL",
"NEW GHINIA",
"NEW ZEALAND",
"NICARAGUA",
"NIGER",
"NIGERIA",
"NORTH KOREA",
"NORWAY",
"PAKISTAN",
"PALAU",
"PALESTINE",
"PANAMA",
"PAPUA NEW GUINEA",
"PARAGUAY",
"PERU",
"PHILIPPINES",
"POLAND",
"PORTUGAL",
"PUERTO RICO",
"QATAR",
"REPUBLIC OF MACEDONIA",
"REPUBLIC OF BELARUS",
"REPUBLIC OF SOMALILAND",
"REPUPLIC OF GUINEA",
"ROMANIA",
"RWANDA",
"RUSSIA",
"SAINT LUCIA",
"SAINT VINSENT",
"SAN MARINO",
"SAO TOME",
"SAUDI ARABIA",
"SENEGAL",
"SICHEL",
"SIERRA LEONE",
"SINGAPORE",
"SLOVAKIA",
"SLOVENIA",
"SOLOMON ISLAND",
"SOMALIA",
"SOUTH AFRICA",
"SOUTH KOREA",
"SOUTH SUDAN",
"SPAIN",
"SRI LANKA",
"ST CHRISTOPHER",
"ST HELENA",
"ST KITTS-NAVIS",
"SUDAN",
"SULTANATE OF OMAN",
"SURBIA",
"SURINAME",
"SWAZILAND",
"SWEDEN",
"SWIZERLAND",
"SYRIA",
"TAHITI",
"TAIWAN",
"TAJIKISTAN",
"TANZANIA",
"TASMANIA",
"THAILAND",
"TIMOR LESTE",
"TOGO",
"TONGA",
"TRINIDAD",
"TUNISIA",
"TURKEY",
"TURKMENISTAN",
"TUVALU",
"UNITED STATES OF AMERICA",
"UGANDA",
"UKRAINE",
"United Nations",
"URGWAY",
"UZBAKISTAN",
"VANUATU",
"VATICAN",
"VENEZUELA",
"VIETNAM",
"W SAMOA",
"YEMEN",
"YUGOSLAVIA",
"ZAMBIA",
"ZIMBABWE"
],
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "marital_status",
"label": "Marital Status",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"SINGLE",
"MARRIED",
"DIVORCED",
"WIDOW",
"UNSPECIFIC"
],
"value": "",
"ocr_field": true,
"oneTimeUse": false
},
{
"name": "have_you_ever_previously_traveled_to_kenya",
"label": "Have you previously traveled to Kenya?",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"YES",
"NO"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false
},
{
"name": "have_you_ever_previously_denied_entry_to_kenya",
"label": "Have you ever been previously denied entry to Kenya?",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"YES",
"NO"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false
},
{
"name": "have_you_ever_been_convicted_of_any_offence_in_last_5_years",
"label": "Have you ever been convicted of any offence, under any system of law, in the past 5 years?",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"YES",
"NO"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false
},
{
"name": "is_your_trip_financed_by_a_third_party_which_is_not_employer_nor_government",
"label": "Is your trip financed by a third party, which is not your employer nor a government?",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"YES",
"NO"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false
}
]
},
{
"name": "customs_declaration",
"label": "Customs Declaration",
"sub_label": "Customs Declaration required for identification purposes in the visa application.",
"type": "group",
"group_elements": [
{
"name": "are_you_bringing_into_republic_of_kenya_currency_or_monetary_instruments_over",
"label": "Will you be bringing into Republic of Kenya currency or monetary instruments of a value greater than $5000 or foreign equivalent?",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"YES",
"NO"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false,
"dependent_elements": [
{
"name": "are_you_bringing_into_republic_of_kenya_currency_or_monetary_instruments_over_information",
"label": "Are you bringing into Republic of Kenya currency or monetary instruments over $5,000.00 US (or foreign equivalent) Information?",
"type": "subGroup",
"dependent_value": "YES",
"sub_group_elements": [
[
{
"name": "select_currency",
"label": "Select Currency",
"dependant_on": "are_you_bringing_into_republic_of_kenya_currency_or_monetary_instruments_over",
"dependant_value": "YES",
"type": "dropdown",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"options": [
"USD",
"KES",
"EUR",
"CNY",
"INR"
],
"value": "",
"ocr_field": false,
"oneTimeUse": false
},
{
"name": "amount",
"label": "Amount",
"dependant_on": "are_you_bringing_into_republic_of_kenya_currency_or_monetary_instruments_over",
"dependant_value": "YES",
"type": "textField",
"is_important": false,
"validations": {
"mandatory": true,
"read_only": false,
"display": true
},
"value": "",
"ocr_field": false,
"oneTimeUse": false
}
]
]
}
]
}
]
}
]
`` |
Beta Was this translation helpful? Give feedback.
You can start optimizing your form by considering the use of uncontrolled Antd Input instead of controlled. It integrates well with the
register
form method.Now, without knowing your actual use-case, there're many different things you can do to optimize the performance of your form. Consider searching though the discussions section of RHF repository for threads like #7611.
The main idea is to subscribe to values as deep down the React tree as possible where the information this info is relevant; make use of hooks like
useWatch
,useFormState
, thegetFieldState
form method, instead of watching the form values and state (errors) at the root of your form. You can also look into thedeps
prop …