Next-Gen Knack features a comprehensive event system built around the Knack.on() method, providing structured data and modern JavaScript patterns for business logic.
What You'll Learn
You'll learn about the event-driven architecture that powers Next-Gen Knack applications. Learn how to listen for page renders, view updates, form submissions, and record changes to trigger business logic at precisely the right moments. This approach separates presentation from logic, creating more maintainable and powerful applications.
Every JavaScript customization must begin with the
Knack.ready()method. This ensures the Knack object is fully initialized and the React application has finished mounting before your custom code executes.
Event Categories
The Knack event system is organized into several main categories:
- Page Events - Triggered when pages are rendered or navigated
- View Events - Fired when specific views are displayed
- Record Events - Occur during data operations (create, update, delete)
- Form Events - Handle form interactions and submissions
Event Naming Conventions
Next-Gen events use a hierarchical naming system that allows both broad and specific event listening:
General Event Patterns
page:render- Any page rendersview:render- Any element rendersform:submit- Any form submitsrecord:create- Any record is created
Specific Event Patterns
page:render:scene_123- Specific page rendersview:render:view_456- Specific element rendersform:submit:view_789- Specific form submits
Type-Specific Event Patterns
view:render:form- Any form view rendersview:render:table- Any table view renderview:render:details- Any details view rendersview:render:list- Any list view renders
Event Data Structures
Each event provides a consistent data object with relevant information:
Page Events
Knack.on('page:render', ({ pageKey }) => {
console.log('Event data:', { pageKey });
// pageKey: string (e.g., 'scene_123')
});
View Events
JavaScript
Knack.on('view:render', ({ viewKey }) => {
console.log('View rendered:', {
viewKey, // e.g., 'view_456'
});
});
Form Events
Knack.on('form:submit', ({ record, viewKey, isEdit }) => {
console.log('Event data:', { record, viewKey, isEdit });
// record: object (form field values after submission)
// viewKey: string (e.g., 'view_456')
// isEdit: boolean (true for edit forms)
});
Form Focus
Overview
The Knack form API allows you to programmatically set field values and focus form inputs using custom JavaScript code. This is useful for automating form filling, creating custom user experiences, and building dynamic form interactions.
Basic Setup
Knack.ready().then(() => {
Knack.on('view:render', ({ viewKey }) => {
const form = Knack.page.getForm(viewKey);
if (form) {
// Your setValue and focus calls here
} else {
console.log('Form not found for view:', viewKey);
}
});
});
API Methods
form.setValue(fieldKey, value) - Sets the value of a form field
form.focus(fieldKey) - Focuses a form field or field component
Field Types Reference
Text Fields
Short Text & Paragraph Text
form.setValue('field_43', "Example Text");
form.focus('field_43');
form.setValue('field_45', "Multi-line paragraph text");
form.focus('field_45');
Rich Text
form.setValue('field_46', "<b>HTML formatted text</b>");
form.focus('field_46');
Numeric Fields
// Number field
form.setValue('field_47', 123);
form.focus('field_47');
// Currency field
form.setValue('field_48', 99.99);
form.focus('field_48');
// Rating field
form.setValue('field_71', 4); // Rating 1-5
form.focus('field_71');
Choice Fields
Single Selection
form.setValue('field_50', "Option Name");
form.focus('field_50');
Multiple Selection
form.setValue('field_51', ["Option 1", "Option 2"]);
form.focus('field_51');
Checkboxes
form.setValue('field_52', ["Selected Option"]);
form.focus('field_52');
Boolean Fields
// Works for dropdown, checkbox, and radio button boolean fields
form.setValue('field_54', "Yes"); // or "No"
form.focus('field_54');
Date & Time Fields
Basic Date/Time
form.setValue('field_57', {
date: new Date('2023-01-01T22:00:00'),
all_day: false
});
// Focus the date input
form.focus('field_57.date');
Date Ranges with Recurring Events
form.setValue('field_59', {
date: {
from: new Date('2023-01-01T14:53:00')
},
repeat: {
frequency: 'weekly',
interval: 2,
weekDays: ['SA', 'SU'],
endson: 'never'
}
});
form.focus('field_59.date');
Name Fields
form.setValue('field_64', {
first: "John",
middle: "Michael",
last: "Doe"
});
// Focus individual name components
form.focus('field_64.first');
form.focus('field_64.middle');
form.focus('field_64.last');
Contact Fields
Email
form.setValue('field_65.email', "[email protected]");
form.focus('field_65.email');
Phone
form.setValue('field_68', "(555) 123-4567");
form.focus('field_68');
Link/URL
form.setValue('field_69.url', "https://example.com");
form.focus('field_69.url');
Address Fields
Standard Address
// Set each address component
form.setValue('field_66.street', "123 Main Street");
form.setValue('field_66.street2', "Suite 100");
form.setValue('field_66.city', "San Francisco");
form.setValue('field_66.state', "CA");
form.setValue('field_66.zip', "94102");
// Focus individual address components
form.focus('field_66.street');
form.focus('field_66.street2');
form.focus('field_66.city');
form.focus('field_66.state');
form.focus('field_66.zip');
Geographic Coordinates
form.setValue('field_67.latitude', "37.7749");
form.setValue('field_67.longitude', "-122.4194");
form.focus('field_67.latitude');
form.focus('field_67.longitude');
Media Fields
Image (URL)
form.setValue('field_63', "https://example.com/image.jpg");
form.focus('field_63');
Limitations & Special Cases
DateTime Time Input Focus Limitation ⚠️
Issue: DateTimePicker components render separate date and time inputs, but the form system only recognizes the main field registration.
// ✅ This works - focuses date input
form.focus('field_57.date');
// ❌ This does NOT work - time input focus not supported
form.focus('field_57.time');
Reason: The DateTimePicker registers as a single field with react-hook-form (field_57.date) even though it renders two DOM inputs. The time input exists in the DOM but is not registered as a separate field, so form.focus('field_57.time') will fail.
Unsupported Field Types
File Upload Fields ❌
Cannot be set programmatically
Files upload immediately upon selection before JavaScript can intercept
Only file IDs are accessible after upload completes
Signature Fields ❌
Cannot be set programmatically
Requires user interaction for drawing/signing
Read-Only System Fields ❌
Record ID, Created On, Updated On, Created By, etc.
These fields are managed automatically by Knack
Error Handling
Knack.ready().then(() => {
Knack.on('view:render', ({ viewKey }) => {
const form = Knack.page.getForm(viewKey);
if (!form) {
console.warn('Form not found for view:', viewKey);
return;
}
try {
form.setValue('field_43', "Test Value");
form.focus('field_43');
} catch (error) {
console.error('Error setting field value:', error);
}
});
});
Best Practices
1. Always Verify Form Exists
const form = Knack.page.getForm(viewKey);
if (!form) {
console.warn('Form not available');
return;
}
2. Use Descriptive Error Handling
try {
form.setValue('field_43', value);
} catch (error) {
console.error(`Failed to set field_43:`, error.message);
}
3. Test Field Access First
// Test if field exists before setting
if (form.fields['field_43']) {
form.setValue('field_43', 'value');
}
4. Handle Async Operations
// For dynamic forms or conditional fields
setTimeout(() => {
const form = Knack.page.getForm(viewKey);
if (form) {
form.setValue('field_43', 'delayed value');
}
}, 100);Record Events
Knack.on('record:create', ({ record, viewKey }) => {
console.log('Record created:', record);
});
Knack.on('record:update', ({ record, viewKey }) => {
console.log('Record updated:', record);
});
Knack.on('record:delete', ({ recordId, viewKey }) => {
console.log('Record deleted:', recordId);
});
Record ID
Knack.getCurrentRecordId() is a function that returns the current page's record ID. It provides the same functionality as the commonly-used Knack.hash_id property in Classic apps, while following our standard naming conventions for Next-Gen custom code functions.
// Get the current record ID
const recordId = Knack.getCurrentRecordId();Basic Event Syntax
All events follow the same pattern using Knack.on():
JavaScript
Knack.ready().then(async () => {
// Listen for any event of this type
Knack.on('event:type', (payload) => {
console.log('Event triggered:', payload);
});
// Listen for a specific event
Knack.on('event:type:specific_id', (payload) => {
console.log('Specific event triggered:', payload);
});
});
Event Data Structure
Each event provides structured data relevant to the event type:
JavaScript
Knack.on('view:render', ({ viewKey }) => {
console.log('View rendered:', {
viewKey, // e.g., 'view_456'
});
});
Best Practices
Use Events for Logic
Events should trigger business logic, data processing, and API calls
// ✅ Good - Business logic
Knack.on('record:create', ({ record, viewKey }) => {
console.log('New record created:', record);
if (record.field_priority === 'High') {
console.log('High priority record, sending notifications');
sendNotificationToManagers(record);
}
});
// ⚠️ Use with caution - DOM manipulation
Knack.on('view:render', ({ viewKey }) => {
document.querySelector('.kn-button').style.color = 'red';
});
Efficient Event Registration
Register events efficiently to avoid performance issues:
// ✅ Efficient - Single listener with conditional logic
Knack.on('view:render', ({ viewKey }) => {
if (viewKey.includes('form')) {
handleFormRender(viewKey);
} else if (viewKey.includes('table')) {
handleTableRender(viewKey);
}
});
// ❌ Inefficient - Multiple similar listeners
for (let i = 1; i <= 50; i++) {
Knack.on(`view:render:view_${i}`, () => {
console.log(`View ${i} rendered`);
});
}
Error Handling in Events
Handle potential errors in event listeners:
Knack.on('form:submit', async ({ record, viewKey }) => {
try {
await processFormSubmission(record);
console.log('Form processed successfully');
} catch (error) {
console.error('Form processing failed:', error);
// Handle error appropriately
}
});
Event Lifecycle
Events follow a predictable lifecycle that you can leverage:
- Application Load -
Knack.ready()resolves - Page Navigation - Page events fire
- View Rendering - View events fire in sequence
- User Interaction - Form and record events fire
- Data Changes - Record events fire with updated data
Understanding this lifecycle helps you place your business logic at the optimal points in your application's flow.

