So I am attempting to retrieve sessions that are set as “Auto” (in the Register Type column of my Sessions Table) so that they automatically appear on a persons customized conference agenda without the user having to take any specific action other than logging in. There are sessions they have to register for and those are labled in the column Register Type as “Manual.” Being fully transparent I am attempting to figure this out with Gemini as I am not a JavaScript master on any level. What am I doing wrong? I ensured the object and field types are correct.
My objective is to automatically create records in a ‘Session Attendance’ object (object_21
) whenever a user is logged in, for any session in my ‘Sessions’ object (object_3
) that has a specific field (Register Type
, field_188
) set to the value “Auto”. This should happen automatically in the background.
Application Details:
- App URL:
https://erau.knack.com/summit2025
- Access Method: The application is accessed directly via its URL (it is not embedded in another website/iframe).
- Authentication: We use SAML SSO (via Okta) for user login.
The Problem: I have been attempting to implement this using custom JavaScript attached to standard Knack events (knack-page-render.any
and knack-scene-render.any
). However, the script consistently fails because the Knack.Api
object appears to be undefined
at the time the script executes, even when including setTimeout
delays.
Diagnostic console logs confirm that the main Knack
object is defined (type object
), but attempting to access Knack.Api
results in undefined
. This prevents any API calls (like Knack.Api.Model.fetchAll
or Knack.Api.Model.create
) from succeeding.
Code Attempted: Here is the latest version of the code we tried, using the knack-scene-render.any
event and diagnostic checks:
// --- Knack JavaScript for Automatic Session Registration ---
// Version 5: Switched to knack-scene-render.any event listener
$(document).on('knack-scene-render.any', function(event, scene) { // *** Using knack-scene-render.any ***
// --- Configuration ---
const SESSION_OBJECT_ID = 'object_3'; // Sessions Object ID
const REGISTER_TYPE_FIELD = 'field_188'; // 'Register Type' field ID on Sessions table
const SESSION_ATTENDANCE_OBJECT_ID = 'object_21'; // Session Attendance Object ID
const SESSION_FIELD_ON_ATTENDANCE = 'field_149'; // Connection to Session on Attendance table
const USER_FIELD_ON_ATTENDANCE = 'field_156'; // Connection to User on Attendance table
// --- End Configuration ---
const checkFlag = 'autoSessionsChecked_v1_' + SESSION_OBJECT_ID;
if (sessionStorage.getItem(checkFlag)) {
return;
}
setTimeout(() => {
const loggedInUser = Knack.getUserAttributes();
if (!loggedInUser || !loggedInUser.id || loggedInUser.id === 'Unknown') {
return;
}
const userId = loggedInUser.id;
if (sessionStorage.getItem(checkFlag)) {
return;
}
console.log(`DEBUG: 1. Running check inside 'knack-scene-render.any' for user: ${userId} (scene: ${scene.key})`);
// Diagnostic Checks
console.log(`DEBUG: Checking Knack object type: ${typeof Knack}`);
if (typeof Knack !== 'undefined') {
console.log(`DEBUG: Checking Knack.Api object type: ${typeof Knack.Api}`);
if (typeof Knack.Api !== 'undefined') {
console.log(`DEBUG: Checking Knack.Api.Model object type: ${typeof Knack.Api.Model}`);
}
}
// Abort if API is not available
if (typeof Knack === 'undefined' || typeof Knack.Api === 'undefined' || typeof Knack.Api.Model === 'undefined') {
console.error("DEBUG: ERROR - Knack API components still undefined even in knack-scene-render. Aborting.");
sessionStorage.setItem(checkFlag, 'true'); // Prevent loops
return;
}
console.log("DEBUG: 1a. Knack API seems available. Attempting to fetch Auto sessions...");
let autoSessionIds = [];
let userRegisteredSessionIds = new Set();
// Fetch Auto Sessions
Knack.Api.Model.fetchAll({
model: SESSION_OBJECT_ID,
filters: [{ field: REGISTER_TYPE_FIELD, operator: 'is', value: 'Auto' }],
auth: 'user'
})
.then(function(autoSessionsResult) {
// Process results and fetch existing attendance... (full logic as provided previously)
if (!autoSessionsResult || !autoSessionsResult.records) { throw new Error("Failed to fetch Auto sessions."); }
autoSessionIds = autoSessionsResult.records.map(record => record.id);
console.log(`DEBUG: 2. Found ${autoSessionIds.length} Auto Session IDs:`, autoSessionIds);
if (autoSessionIds.length === 0) { return { records: [] }; }
console.log("DEBUG: 3. Fetching existing attendance records for user...");
return Knack.Api.Model.fetchAll({ model: SESSION_ATTENDANCE_OBJECT_ID, filters: [{ field: USER_FIELD_ON_ATTENDANCE, operator: 'is', value: userId }], auth: 'user' });
})
.then(function(attendanceResult) {
// Process attendance and determine needed registrations... (full logic as provided previously)
if (!attendanceResult || !attendanceResult.hasOwnProperty('records')) { throw new Error("Failed fetching attendance."); }
console.log(`DEBUG: 4. Fetched ${attendanceResult.records.length} existing attendance records.`);
attendanceResult.records.forEach(record => { const conn = record[SESSION_FIELD_ON_ATTENDANCE + '_raw']; if (conn && conn.length > 0) { userRegisteredSessionIds.add(conn[0].id); } });
console.log('DEBUG: 5. User registered for IDs:', Array.from(userRegisteredSessionIds));
const sessionsToRegister = autoSessionIds.filter(id => !userRegisteredSessionIds.has(id));
console.log('DEBUG: 6. Sessions needing registration:', sessionsToRegister);
if (sessionsToRegister.length === 0) { return []; }
console.log(`DEBUG: 7. Attempting to create ${sessionsToRegister.length} records...`);
// Create missing records... (full logic as provided previously)
const createPromises = sessionsToRegister.map(sessionId => { const d = {}; d[USER_FIELD_ON_ATTENDANCE] = userId; d[SESSION_FIELD_ON_ATTENDANCE] = sessionId; return Knack.Api.Model.create({ model: SESSION_ATTENDANCE_OBJECT_ID, data: d, auth: 'user' }); });
return Promise.all(createPromises);
})
.then(function(creationResults) {
// Final logging... (full logic as provided previously)
console.log('DEBUG: 8. Processing creation results.');
if (creationResults.length > 0) { console.log(`DEBUG: 8a. Successfully created ${creationResults.length} records.`); } else { console.log('DEBUG: 8b. No new records created.'); }
sessionStorage.setItem(checkFlag, 'true');
console.log('DEBUG: 9. Check complete.');
})
.catch(function(error) {
console.error('DEBUG: FINAL ERROR during process:', error);
});
}, 300);
});
Console Output Evidence: The console logs consistently show DEBUG: Checking Knack.Api object type: undefined
, followed by the error message indicating the script is aborting because the API components are undefined. I can provide screenshots of this console output if needed.