如何在React中映射并获取Froala编辑器添加的表单输入数据?
解决React中Froala编辑器生成表单无法获取输入数据的问题
因为通过dangerouslySetInnerHTML或FroalaEditorView渲染的表单元素不属于React虚拟DOM管控范围,React无法直接通过受控组件方式绑定state,需要手动操作DOM来收集输入数据,以下是两种可行方案:
方案1:监听表单提交事件,一次性收集所有数据
给渲染表单的容器添加ref,在组件挂载后监听表单的submit事件,手动遍历所有表单元素获取值:
import { useRef, useEffect } from 'react'; function OfferLetterView({ content }) { const formContainerRef = useRef(null); useEffect(() => { const handleSubmit = (e) => { e.preventDefault(); // 收集所有表单数据 const formData = new FormData(e.target); // 转为普通对象 const formValues = Object.fromEntries(formData.entries()); console.log('候选人提交的数据:', formValues); // 这里可以将数据发送到后端或做其他处理 }; const formElement = formContainerRef.current.querySelector('form'); if (formElement) { formElement.addEventListener('submit', handleSubmit); // 清理监听 return () => formElement.removeEventListener('submit', handleSubmit); } }, [content]); return ( <div className="mt-20" ref={formContainerRef}> <div dangerouslySetInnerHTML={{ __html: content }} /> </div> ); }
方案2:实时监听输入变化,同步更新state
如果需要实时获取输入数据,可以遍历所有输入元素,给它们添加change或input事件监听:
import { useRef, useEffect, useState } from 'react'; function OfferLetterView({ content }) { const formContainerRef = useRef(null); const [formValues, setFormValues] = useState({}); useEffect(() => { const updateFormValues = (element) => { const name = element.name; let value; if (element.type === 'radio') { value = element.checked ? element.value : undefined; } else if (element.type === 'checkbox') { value = element.checked; } else { value = element.value; } setFormValues(prev => ({ ...prev, [name]: value })); }; const setupEventListeners = () => { const inputElements = formContainerRef.current.querySelectorAll('input, textarea, select'); inputElements.forEach(el => { el.addEventListener('change', () => updateFormValues(el)); // 文本框可以监听input事件实时更新 if (el.type === 'text' || el.tagName === 'TEXTAREA') { el.addEventListener('input', () => updateFormValues(el)); } }); // 清理所有监听 return () => { inputElements.forEach(el => { el.removeEventListener('change', () => updateFormValues(el)); if (el.type === 'text' || el.tagName === 'TEXTAREA') { el.removeEventListener('input', () => updateFormValues(el)); } }); }; }; // 内容更新时重新设置监听 const cleanup = setupEventListeners(); return cleanup; }, [content]); return ( <div className="mt-20" ref={formContainerRef}> <div dangerouslySetInnerHTML={{ __html: content }} /> {/* 可以实时展示收集到的数据 */} <pre>{JSON.stringify(formValues, null, 2)}</pre> </div> ); }
注意事项
- 确保Froala编辑器生成的表单元素都带有
name属性,否则无法通过FormData或name属性识别字段 - 如果表单中有多个单选按钮,要保证同一组单选按钮的
name属性一致 - 每次
content更新时,需要重新绑定事件监听,因为DOM元素会被重新渲染
内容的提问来源于stack exchange,提问作者Hetal N
相关产品推荐
相关产品推荐

