Skip to content

fix: make textarea visible before TinyMCE init on edit#878

Open
Deftunk wants to merge 1 commit into
LINCnil:masterfrom
Deftunk:fix/tinymce-init-on-hidden-textarea
Open

fix: make textarea visible before TinyMCE init on edit#878
Deftunk wants to merge 1 commit into
LINCnil:masterfrom
Deftunk:fix/tinymce-init-on-hidden-textarea

Conversation

@Deftunk
Copy link
Copy Markdown

@Deftunk Deftunk commented May 6, 2026

Problem

When clicking on the body of a question or measure that already has content (answer.length > 0), the editor opens visually empty: the rendered <div> is hidden (because editor becomes truthy) and the TinyMCE iframe stays invisible.

Result: the user thinks their content has been wiped, even though the data is preserved in IndexedDB.

This happens every time an imported structure or PIA is edited — every answer is pre-filled at import, so every textarea has hideTextarea = true.

Root cause

In ngOnInit, the component sets:

this.hideTextarea = this.question.answer?.length > 0;

The textarea then has the .hide CSS class, which is display: none !important in styles.scss.

When the user clicks to edit, loadEditor() calls tinymce.init({ selector: '#' + elementId }) on a textarea that is display: none. TinyMCE 8 + the autoresize plugin fails silently in this case: the iframe is created but its height stays at 0 because layout calculations on a hidden ancestor return 0.

The user sees nothing — and clicking elsewhere triggers focusout, which writes the (empty) editor content back to the form, although in practice the existing answer is preserved on next display because getContent() returns whatever the editor parsed at init.

Fix

In questionContentFocusIn and measureContentFocusIn, set hideTextarea = false so the textarea is visible before TinyMCE attaches, and defer loadEditor() to the next macrotask so Angular has time to apply the class change to the DOM:

this.hideTextarea = false;
setTimeout(() => this.loadEditor(), 0);

Scope

Applied to all 4 components that use the same pattern:

  • src/app/modules/structure/content/questions/questions.component.ts
  • src/app/modules/structure/content/measures/measures.component.ts
  • src/app/modules/pia/content/questions/questions.component.ts
  • src/app/modules/pia/content/measures/measures.component.ts

Total: +10 / -2 lines.

How to reproduce (before the fix)

  1. Import any structure or PIA that has answers.
  2. Click on the body of a question with content.
  3. The section appears to collapse / wipe — the editor doesn't show.

After the fix

The textarea becomes visible before TinyMCE initializes; the editor renders correctly with the existing content.

When clicking on a question/measure body that already has content
(answer.length > 0), `hideTextarea` is true and the underlying textarea
has `display: none !important` from the .hide CSS class.

TinyMCE 8 + autoresize plugin fails silently when initialized on a
hidden element: the editor iframe is created but stays at height 0
and the rendered <div> is also hidden because `editor` is now set,
leaving the user with an empty-looking section.

This affects every imported PIA/structure (every answer is pre-filled,
so every textarea is hidden), and also re-edits of fields already
written in the app.

Fix: in `questionContentFocusIn` / `measureContentFocusIn`, set
`hideTextarea = false` to make the textarea visible, then defer
`loadEditor()` to the next tick so Angular has time to apply the
class change before TinyMCE attaches.

Applied to both structure and pia modules, for both questions and
measures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant