fix(apps): stop re-serialising the config section, which killed its listeners
Every themed dropdown on the app config page was dead: it rendered, but
clicking did nothing. Only that page — every other dropdown in the WebUI
worked.
renderAppDetail captured the config section's own innerHTML right after
displayConfigForm() had rendered it...
const configHTML = document.getElementById('config-section')?.innerHTML;
...67 lines later...
configSection.innerHTML = configHTML;
...and wrote the same string straight back. That is a no-op for the
markup and a catastrophe for behaviour: re-assigning innerHTML re-parses
the subtree, so every listener in it is destroyed.
custom-select.js had already wrapped each <select>, so the captured
string contained the .custom-select wrapper and the custom-select-native
class. The re-inserted copy therefore looked enhanced — which made the
enhancer correctly skip it as already-done — while having no click
handler at all. A dropdown that renders perfectly and does nothing.
The container is never wholesale-rewritten in that function (it updates
header/config/console individually), so the capture-and-restore had no
purpose. Both lines removed, with a comment stating that anything added
there must mutate the section rather than re-assign its innerHTML.
Diagnosed in a real browser rather than by reading: instrumenting
CustomSelect.build() showed the enhancer DID build a widget for the field
while the wrapper in the DOM was not the one it built, and patching the
innerHTML setter named apps-manager.js:785 as the writer. Verified live:
the dropdown opens, and picking an option sets the value (auto) and the
label.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
07daa7555a
commit
47b614f8b4
@ -714,8 +714,6 @@ class AppsManager {
|
||||
// Render config section with working app-config-original.js approach
|
||||
// Use the working displayConfigForm from app-config-original.js
|
||||
await this.displayConfigForm(app, preferredCategory);
|
||||
|
||||
const configHTML = document.getElementById('config-section')?.innerHTML || '';
|
||||
|
||||
// Initialize port managers after config form is rendered
|
||||
setTimeout(async () => {
|
||||
@ -778,15 +776,17 @@ class AppsManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Update config section
|
||||
const configSection = document.getElementById('config-section');
|
||||
//// // console.log('config-section element found:', !!configSection);
|
||||
if (configSection) {
|
||||
configSection.innerHTML = configHTML;
|
||||
//// // console.log('Config section updated successfully, innerHTML length:', configHTML.length);
|
||||
} else {
|
||||
console.error('config-section element not found in DOM');
|
||||
}
|
||||
// The config section is DELIBERATELY not touched here. displayConfigForm()
|
||||
// above already rendered it, and this used to capture its innerHTML and
|
||||
// write the same string back a few lines later. That round-trip is a no-op
|
||||
// for the markup but re-parses the subtree, so every listener attached to
|
||||
// it is destroyed — which silently killed every themed dropdown on the app
|
||||
// config page: custom-select.js had already wrapped each <select>, so the
|
||||
// re-inserted copy carried the .custom-select markup (and therefore was
|
||||
// skipped by the enhancer as "already done") while having no click handler.
|
||||
// The container is never wholesale-rewritten in this function, so there is
|
||||
// nothing to restore. Anything added here must MUTATE the section, never
|
||||
// re-assign its innerHTML.
|
||||
|
||||
// Update console section (preserve original structure)
|
||||
const consoleSection = container.querySelector('.console-section');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user