Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions dwertheimer.Forms/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@

See Plugin [README](https://github.com/NotePlan/plugins/blob/main/dwertheimer.Forms/README.md) for details on available commands and use case.

## [1.0.15] 2026-01-18 @dwertheimer

### Fixed
- **CRITICAL: Null Value Handling**: Fixed `TypeError: null is not an object (evaluating 'Object.getOwnPropertyNames')` error that occurred when templating plugin tried to process form data containing null values. Added explicit null checks in `JSP`, `getFilteredProps`, and `getAllPropertyNames` helper functions to handle null values correctly (since `typeof null === 'object'` in JavaScript).
- **Form Submission Success Detection**: Fixed issue where successful form submissions were incorrectly flagged as errors. When `templateRunner` successfully creates a note via `templateNew`, it returns `undefined` (which is valid), but the code was treating this as an error. Now only `null` or empty strings are treated as errors.
- **Deep Null Sanitization**: Added comprehensive deep sanitization of null/undefined values throughout form data processing. All null/undefined values are now converted to empty strings recursively before being passed to the templating engine, preventing errors in nested data structures.
- **setTimeout Removal**: Removed `setTimeout` usage in form submission handlers (not available in NotePlan's JSContext). Replaced with proactive cleanup mechanism using a Map to manage debouncing without timeouts.

### Changed
- **templateNew Return Value**: Updated `templateNew` to return the filename (string) on success or `null` on failure, making the API more consistent and explicit. Previously returned `undefined`, which made it difficult to distinguish success from failure.
- **templateRunner Return Value**: Updated `templateRunner` to return the filename when a note is successfully created, instead of returning `undefined`. This provides explicit feedback about successful operations.
- **Error Messages**: Improved error messages to be more specific about null value issues and provide better guidance for debugging template execution problems.

## [1.0.14] 2026-01-18 @dwertheimer

### Fixed
- **Form Submission Error Detection**: Fixed issue where FormBrowserView showed success message even when template execution failed. Now properly detects and displays errors from template processing, including AI analysis results and form submission errors.
- **Form Field Validation**: Added validation to ensure all form fields are included in submission, even if left blank. This prevents template errors from missing variables. Validation now occurs both in FormBrowserView handler and in handleSubmitButtonClick.
- **Error Message Display**: Improved error messages to be more specific. FormBrowserView now shows detailed error messages instead of generic "success" when template execution fails. Error messages include information about missing variables and template rendering issues.

## [1.0.13] 2026-01-18 @dwertheimer

### Changed
Expand Down
4 changes: 2 additions & 2 deletions dwertheimer.Forms/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"noteplan.minAppVersion": "3.4.0",
"plugin.id": "dwertheimer.Forms",
"plugin.name": "📝 Template Forms",
"plugin.version": "1.0.13",
"plugin.version": "1.0.15",
"plugin.releaseStatus": "beta",
"plugin.lastUpdateInfo": "Dark Mode CSS theme color fixes, FormPreview scaled warning improvements, text color styling updates, Form Browser @Templates support, Toast notifications, fixed form submission to include all fields, and fixed Target Note field to use template values for special options",
"plugin.lastUpdateInfo": "Fixed critical null value handling in templating plugin, fixed form submission success detection, added deep null sanitization, and improved API consistency",
"plugin.description": "Dynamic Forms for NotePlan using Templating -- fill out a multi-field form and have the data sent to a template for processing",
"plugin.author": "dwertheimer",
"plugin.requiredFiles": ["react.c.FormView.bundle.dev.js", "react.c.FormBuilderView.bundle.dev.js", "react.c.FormBrowserView.bundle.dev.js"],
Expand Down
82 changes: 79 additions & 3 deletions dwertheimer.Forms/src/components/FormBrowserView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,17 @@ export function FormBrowserView({
const handleSave = useCallback(
(formValues: Object, windowId?: string) => {
logDebug('FormBrowserView', 'Form submitted:', formValues)

// Clear any previous errors before submitting
dispatch('UPDATE_DATA', {
...data,
pluginData: {
...pluginData,
formSubmissionError: '',
aiAnalysisResult: '',
},
})

// Send to plugin for processing
// Include keepOpenOnSubmit flag so the plugin knows not to close the window
if (requestFromPlugin) {
Expand All @@ -537,6 +548,60 @@ export function FormBrowserView({
})
.then((responseData) => {
logDebug('FormBrowserView', 'Form submission response:', responseData)

// Check if the response indicates success or failure
// The responseData may be the data object from a successful response, or it may contain error info
if (responseData && typeof responseData === 'object') {
// Check for error indicators in the response (from pluginData)
const pluginDataFromResponse = responseData.pluginData || {}
const hasError = pluginDataFromResponse.formSubmissionError || pluginDataFromResponse.aiAnalysisResult || responseData.formSubmissionError || responseData.aiAnalysisResult
if (hasError) {
// Extract error message
let errorMessage = 'Form submission failed.'
const formError = pluginDataFromResponse.formSubmissionError || responseData.formSubmissionError
const aiError = pluginDataFromResponse.aiAnalysisResult || responseData.aiAnalysisResult

if (formError) {
errorMessage = formError
} else if (aiError) {
// Extract a brief summary from AI analysis
const aiMsg = aiError
const firstLine = aiMsg.split('\n')[0] || aiMsg.substring(0, 200)
errorMessage = `Template error: ${firstLine}`
}

logError('FormBrowserView', `Form submission failed: ${errorMessage}`)

// Update pluginData with error so FormErrorBanner can display it
dispatch('UPDATE_DATA', {
...data,
pluginData: {
...pluginData,
formSubmissionError: formError || errorMessage,
aiAnalysisResult: aiError || '',
},
})

dispatch('SHOW_TOAST', {
type: 'ERROR',
msg: errorMessage,
timeout: 10000, // Longer timeout for error messages
})
// Don't reset form on error - keep it open so user can fix and retry
return
}
}

// Clear any errors on successful submission
dispatch('UPDATE_DATA', {
...data,
pluginData: {
...pluginData,
formSubmissionError: '',
aiAnalysisResult: '',
},
})

// Show success toast with note information
let successMessage = 'Your form has been submitted successfully.'
if (responseData?.noteTitle) {
Expand Down Expand Up @@ -568,16 +633,27 @@ export function FormBrowserView({
logError('FormBrowserView', `Error submitting form: ${error.message}`)
// On error, show Toast notification but don't close the window
// The window should stay open so user can fix and retry
const errorMessage = error.message || 'An error occurred while submitting the form'

// Update pluginData with error so FormErrorBanner can display it
dispatch('UPDATE_DATA', {
...data,
pluginData: {
...pluginData,
formSubmissionError: errorMessage,
},
})

dispatch('SHOW_TOAST', {
type: 'ERROR',
msg: error.message || 'An error occurred while submitting the form',
timeout: 5000,
msg: errorMessage,
timeout: 10000, // Longer timeout for error messages
})
// Don't reset form on error - let user see what they entered
})
}
},
[selectedTemplate, requestFromPlugin, handleCancel, dispatch],
[selectedTemplate, requestFromPlugin, handleCancel, dispatch, data, pluginData],
)


Expand Down
Loading