Overview
The ION Job Application web form dynamically loads and renders screening questions based on the selected Job Opening. This provides a seamless application experience while capturing structured data for scoring and evaluation.The web form is configured in
ion_career/ion_career/web_form/ion_job_application/ion_job_application.jsonHow It Works
The dynamic form system consists of three main components:- Web Form Configuration: Defines the base fields and layout
- Client-Side JavaScript: Handles dynamic question loading and validation
- Server API: Fetches questions for the selected job opening
Form Structure
The base web form includes standard fields:Links to Job Opening. Once selected, becomes read-only to prevent confusion.
Full name of the applicant.
Email address with built-in validation.
Optional contact number.
Links to Country doctype.
Optional cover letter text.
Resume file upload.
How the applicant found the job (links to Job Applicant Source).
Container where dynamic questions are rendered.
Dynamic Question Rendering
The client-side JavaScript dynamically loads and renders questions when a Job Opening is selected.Lifecycle Hooks
Once a job is selected, the field becomes read-only to prevent accidental changes that would invalidate the loaded questions.
Loading Questions
Theload_job_questions() function fetches questions via API call:
Rendering Questions
Questions are rendered as HTML based on theirinput_type:
Questions are HTML-escaped using
frappe.utils.escape_html() to prevent XSS attacks.Client-Side Validation
The form implements comprehensive client-side validation before submission.Answer Synchronization
As users interact with questions, their answers are synced to a hidden JSON field:Required Field Validation
Before form submission, all required questions are validated:Input Types
The form supports two input types:- Select Dropdown
- Checkbox
Renders as a dropdown with three options:
- Empty (no selection)
- Yes
- No
Data Flow
Server Response
Server returns array of questions with their properties (question text, fieldname, input_type, required).
Dynamic Rendering
Questions are rendered as HTML and inserted into the Screening Questions container.
User Interaction
As user answers questions, the
sync_answers_to_hidden_field() function updates the hidden JSON field.Server Processing
After submission, theprocess_job_questions handler processes the answers:
See the full implementation in
ion_career/handlers.py:4-41Best Practices
Performance Optimization
Performance Optimization
- Questions are loaded once when job is selected
- Event listeners are attached in batch after rendering
- No unnecessary re-renders during answer changes
Security
Security
- All question text is HTML-escaped to prevent XSS
- Answers are validated server-side as well
- Field names are auto-generated to prevent conflicts
User Experience
User Experience
- Job field becomes read-only after selection
- Required questions are clearly marked with asterisk
- Validation errors are user-friendly and specific
- Form freezes during API calls to prevent duplicate submissions
Customization
You can extend the web form by:- Adding Custom Validations: Extend
frappe.web_form.validate()with additional logic - Styling: Add CSS classes to
.job-questions-wrapperand.job-question-item - New Input Types: Modify
render_questions()to support additional field types - Conditional Logic: Show/hide questions based on previous answers