Vários editores de texto rico na mesma página

RichTextEditor

Crie um formulário com dois editores, IDs exclusivos, HTML separado e redefinição com confirmação.

Mantenha uma instância por campo

Um formulário de produto pode precisar de resumo e descrição. Crie um editor por contêiner e mantenha as referências em um mapa. Carregue CSS, núcleo e plugins uma única vez. Não reutilize IDs nem sobrescreva as instâncias em uma variável. São documentos independentes, não raízes de um documento compartilhado.

Execute o exemplo completo

Sirva os arquivos pela aplicação. O exemplo mostra o HTML atual como JSON com textContent, sem innerHTML. Não salva nem envia requisições. Restaurar só o resumo mantém os detalhes; restaurar ambos exige confirmação. Alterações limpam a prévia antiga.

<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css">
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/all_plugins.js"></script>
<style>body{font:16px/1.6 system-ui;max-width:960px;margin:24px auto;padding:0 16px}section{min-width:0;margin-block:20px}.editor-scroll{max-width:100%;overflow-x:auto}button{min-height:44px;padding:8px 16px;margin:8px 8px 0 0}pre{white-space:pre-wrap;overflow-wrap:anywhere}</style>
<h1>Two editors, two independent fields</h1>
<form id="product-form">
  <section aria-labelledby="summary-heading">
    <h2 id="summary-heading">Summary</h2>
    <div class="editor-scroll"><div id="summary-editor"></div></div>
    <button type="button" id="restore-summary">Restore summary</button>
  </section>
  <section aria-labelledby="details-heading">
    <h2 id="details-heading">Details</h2>
    <div class="editor-scroll"><div id="details-editor"></div></div>
  </section>
  <button type="submit">Inspect both fields</button>
  <button type="reset">Restore both fields</button>
  <p id="status" role="status" aria-live="polite"></p>
  <pre id="payload"></pre>
</form>
<script>
// Load the assets once. Give every host its own unique ID and instance.
const initial = {
  summary: "<p>A short <strong>product summary</strong>.</p>",
  details: "<h2>Details</h2><p>A separate document with its own formatting.</p>"
};
const editors = {
  summary: new RichTextEditor("#summary-editor", { toolbar: "full", height: "240px" }),
  details: new RichTextEditor("#details-editor", { toolbar: "full", height: "320px" })
};
const form = document.getElementById("product-form");
const status = document.getElementById("status");
const output = document.getElementById("payload");
function resetFields() {
  for (const key of Object.keys(editors)) editors[key].setHTMLCode(initial[key]);
}
resetFields();
function invalidatePreview() {
  output.textContent = "";
  status.textContent = "Draft changed. Inspect again to see current values.";
}
for (const instance of Object.values(editors)) instance.attachEvent("change", invalidatePreview);
document.getElementById("restore-summary").addEventListener("click", () => {
  if (!confirm("Restore only the summary?")) return;
  editors.summary.setHTMLCode(initial.summary);
  invalidatePreview();
});
form.addEventListener("reset", event => {
  if (!confirm("Restore both documents?")) { event.preventDefault(); return; }
  resetFields();
  output.textContent = "";
  status.textContent = "Both initial documents restored. Nothing saved.";
});
function collect() {
  return Object.fromEntries(Object.entries(editors).map(([key, instance]) => [key, instance.getHTMLCode()]));
}
form.addEventListener("submit", event => {
  event.preventDefault();
  // Read both live instances now; never use whichever editor last had focus.
  output.textContent = JSON.stringify(collect(), null, 2);
  status.textContent = "Current fields shown below. No request sent.";
});
window.multipleDemo = { editors, initial, collect };
</script>

Salve e valide cada campo

Use chaves estáveis como summary e details. Leia ambas as instâncias no envio, independentemente do último foco. O servidor deve autorizar o registro, validar e sanitizar cada HTML. Em erros, preserve os dois rascunhos e indique o campo afetado. Defina se o par deve ser salvo atomicamente.

Coordene salvamento automático e redefinição

Use uma chave por documento ou um registro versionado para o par. Compartilhar uma chave local pode sobrescrever outro rascunho. Redefinir no navegador não cancela gravações no servidor, exclui arquivos nem cria backup. Defina primeiro a fila e a política de versões.

Lista de aceitação

Edite os dois campos e alterne o foco antes de inspecionar. Restaure um e confirme que o outro HTML é idêntico. Cancele a redefinição completa. Teste JSON longo, emoji, teclado e telas de 320px. Muitas barras completas consomem memória e espaço: meça o formulário antes de criar dezenas de instâncias.

Leia a seguir