我正在构建reactjs应用程序。
我已经创建了RichEditor的一个变体 - 它使用了draft.js - 我不确定如何为这个编辑器设置内容,以及如果要将其作为表单的一部分,如何检索它。
这是我目前的代码库
所以,如果我将其视为一个领域。
const initialValues = {editor: "I am a <h2>bit</h2> of dummy <b>html</b> text"}
<RichEditor initialValues={initialValues} />
^所以这样的事情 - 但如果它像反应还原形式一样,我将如何获得内容?
像这样?import React from 'react'
import { Field, reduxForm } from 'redux-form'
import renderField from '../_SharedFormComponents/renderField'
import validate from './validateComplaint'
import warn from './warnComplaint'
const ComplaintSyncValidationForm= props => {
const { handleSubmit, pristine, reset, submitting } = props
const initialValues = {editor: "I am a <h2>bit</h2> of dummy <b>html</b> text"}
return (
<form onSubmit={handleSubmit}>
<Field name="email" type="email" component={renderField} label="Email" />
<RichEditor initialValues={initialValues} />
<div>
<button type="submit" disabled={submitting}>
Complain
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'syncValidationComplaint', // a unique identifier for this form
validate, // <--- validation function given to redux-form
warn // <--- warning function given to redux-form
})(ComplaintSyncValidationForm)
// RichEditor.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Editor, EditorState, RichUtils} from 'draft-js';
import './RichEditor.scss';
class RichEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.focus = () => this.refs.editor.focus();
this.onChange = (editorState) => this.setState({editorState});
this.handleKeyCommand = this._handleKeyCommand.bind(this);
this.onTab = this._onTab.bind(this);
this.toggleBlockType = this._toggleBlockType.bind(this);
this.toggleInlineStyle = this._toggleInlineStyle.bind(this);
}
_handleKeyCommand(command, editorState) {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
_onTab(e) {
const maxDepth = 4;
this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth));
}
_toggleBlockType(blockType) {
this.onChange(
RichUtils.toggleBlockType(
this.state.editorState,
blockType
)
);
}
_toggleInlineStyle(inlineStyle) {
this.onChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
inlineStyle
)
);
}
render() {
const {editorState} = this.state;
// If the user changes block type before entering any text, we can
// either style the placeholder or hide it. Let's just hide it now.
let className = 'RichEditor-editor';
var contentState = editorState.getCurrentContent();
if (!contentState.hasText()) {
if (contentState.getBlockMap().first().getType() !== 'unstyled') {
className += ' RichEditor-hidePlaceholder';
}
}
return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={editorState}
onToggle={this.toggleBlockType}
/>
<InlineStyleControls
editorState={editorState}
onToggle={this.toggleInlineStyle}
/>
<div className={className} onClick={this.focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
onTab={this.onTab}
placeholder="Tell a story..."
ref="editor"
spellCheck={true}
/>
</div>
</div>
);
}
}
// Custom overrides for "code" style.
const styleMap = {
CODE: {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
fontSize: 16,
padding: 2,
},
};
function getBlockStyle(block) {
switch (block.getType()) {
case 'blockquote': return 'RichEditor-blockquote';
default: return null;
}
}
class StyleButton extends React.Component {
constructor() {
super();
this.onToggle = (e) => {
e.preventDefault();
this.props.onToggle(this.props.style);
};
}
render() {
let className = 'RichEditor-styleButton';
if (this.props.active) {
className += ' RichEditor-activeButton';
}
return (
<span className={className} onMouseDown={this.onToggle}>
{this.props.label}
</span>
);
}
}
const BLOCK_TYPES = [
{label: 'H1', style: 'header-one'},
{label: 'H2', style: 'header-two'},
{label: 'H3', style: 'header-three'},/*
{label: 'H4', style: 'header-four'},
{label: 'H5', style: 'header-five'},
{label: 'H6', style: 'header-six'},
{label: 'Blockquote', style: 'blockquote'},
{label: 'UL', style: 'unordered-list-item'},
{label: 'OL', style: 'ordered-list-item'},
{label: 'Code Block', style: 'code-block'},*/
];
const BlockStyleControls = (props) => {
const {editorState} = props;
const selection = editorState.getSelection();
const blockType = editorState
.getCurrentContent()
.getBlockForKey(selection.getStartKey())
.getType();
return (
<div className="RichEditor-controls">
{BLOCK_TYPES.map((type) =>
<StyleButton
key={type.label}
active={type.style === blockType}
label={type.label}
onToggle={props.onToggle}
style={type.style}
/>
)}
</div>
);
};
var INLINE_STYLES = [
{label: 'Bold', style: 'BOLD'},
{label: 'Italic', style: 'ITALIC'},
{label: 'Underline', style: 'UNDERLINE'},
//{label: 'Monospace', style: 'CODE'},
];
const InlineStyleControls = (props) => {
var currentStyle = props.editorState.getCurrentInlineStyle();
return (
<div className="RichEditor-controls">
{INLINE_STYLES.map(type =>
<StyleButton
key={type.label}
active={currentStyle.has(type.style)}
label={type.label}
onToggle={props.onToggle}
style={type.style}
/>
)}
</div>
);
};
export default RichEditor
和它的scss。
// RichEditor.scss
@import '../../colors.scss';
.RichEditor-root {
background: $white;
border: 1px solid $stone-grey;
font-family: 'Georgia', serif;
font-size: 14px;
padding: 15px;
}
.RichEditor-hidePlaceholder .public-DraftEditorPlaceholder-root {
display: none;
}
.RichEditor-controls {
font-family: 'Helvetica', sans-serif;
font-size: 14px;
margin-bottom: 5px;
user-select: none;
}
.RichEditor-styleButton {
color: $grey;
cursor: pointer;
margin-right: 16px;
padding: 2px 0;
display: inline-block;
}
.RichEditor-activeButton {
color: $light-blue;
}
.RichEditor-editor {
border-top: 1px solid $grey;
color: black;
cursor: text;
font-size: 16px;
margin-top: 10px;
.RichEditor-blockquote {
border-left: 5px solid $stone-grey;
color: #666;
font-family: 'Hoefler Text', 'Georgia', serif;
font-style: italic;
margin: 16px 0;
padding: 10px 20px;
}
.public-DraftStyleDefault-pre {
background-color: rgba(0, 0, 0, 0.05);
font-family: 'Inconsolata', 'Menlo', 'Consolas', monospace;
font-size: 16px;
padding: 20px;
}
.public-DraftEditorPlaceholder-root,
.public-DraftEditor-content {
margin: 0 -15px -15px;
padding: 15px;
}
.public-DraftEditor-content {
min-height: 100px;
}
h2{
color: $black!important;
}
}
答案 0 :(得分:0)
我将richtexteditor作为react-redux组件的一部分。它更新了keyups上的一个隐藏字段..它必须改变值而不是设置状态 - 这是为了欺骗现场已被触及的反应 - 还原形式&#34; ---虽然它没有像我想的那样完全复杂 - 如果显示清晰值按钮 - 将重置隐藏字段但不能恢复编辑器中的旧文本。
// renderRichFieldTextarea react-redux field。
import React from 'react'
import RichEditor from '../_SharedGlobalComponents/RichEditor';
class ContentContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
value: this.props.input.value
};
this.handler = this.handler.bind(this);
}
handler(d) {
this.props.input.onChange(d);
}
render() {
const input = this.props.input;
const placeholder = this.props.placeholder;
const type = this.props.type;
const boxclass = this.props.boxclass;
return (
<div>
<RichEditor
initialValues={input.value}
handler={this.handler}
/>
<input {...input} type="hidden" />
</div>
);
}
}
const renderRichFieldTextarea = ({input, label, placeholder, boxclass, type, meta: {touched, error, warning}}) => (
<div className='field'>
<div>
<label>{label}</label>
</div>
<div>
<ContentContainer initialValues={input.value} onChange={this.onChange} input={input} placeholder={placeholder} type={type} boxclass={boxclass}/>
</div>
</div>
)
export default renderRichFieldTextarea
所以我在像这样的表单组件中使用它。
// EditPrivacySectionsSyncValidationForm - 反应还原形式
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import { Row, Col, Collapse } from 'antd';
import renderField from '../_SharedFormComponents/renderField'
import renderRichFieldTextarea from '../_SharedFormComponents/renderRichFieldTextarea'
import renderRadioCheckField from '../_SharedFormComponents/renderRadioCheckField'
import renderError from '../_SharedFormComponents/renderError'
import validate from './validateEditSections'
import warn from './warnEditSections'
const Panel = Collapse.Panel;
const EditPrivacySectionsSyncValidationForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit} >
<Row>
<Col xs={24} sm={24} md={24}>
<div>
<Field name="privacy" type="textarea" component={renderRichFieldTextarea} label="Privacy" placeholder="Please write here..." boxclass="tall"/>
</div>
</Col>
</Row>
<div>
<button type="submit" disabled={submitting}>
Submit
</button>{/*
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>*/}
</div>
</form>
)
}
//initialValues = {interest: "art"}
export default reduxForm({
form: 'syncValidationEditPrivacySections', // a unique identifier for this form
validate, // <--- validation function given to redux-form
warn // <--- warning function given to redux-form
})(EditPrivacySectionsSyncValidationForm)