react-adminlte-components
Version:
React Components that use AdminLTE theme
187 lines (166 loc) • 4.77 kB
JSX
import React from 'react';
import { PropTypes } from 'prop-types';
import { EditorState, convertToRaw, ContentState } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import draftToHtml from 'draftjs-to-html';
import htmlToDraft from 'html-to-draftjs';
import { ShowIf } from 'components/utils';
import {validatable} from 'components/utils';
import shortid from 'shortid';
import style from './_textarea.scss';
import {Articles} from 'api';
class RichTextarea extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
value: (typeof this.props.value != "undefined" && this.props.value != null) ? this.props.value.toString() : '',
isValid: true,
validationText: this.props.validationText
}
this.id = shortid();
this.state = {
editorState: this.contentState(this.props.value)
}
}
contentState(value) {
const contentBlock = htmlToDraft(value);
if (contentBlock) {
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
const editorState = EditorState.createWithContent(contentState);
return editorState;
} else {
return EditorState.createEmpty();
}
}
value() {
return this.state.value;
}
componentWillReceiveProps(nextProps) {
if (this.props.value != nextProps.value) {
let value = (typeof nextProps.value != "undefined" && nextProps.value != null) ? nextProps.value.toString() : '';
this.setState({
value: value,
editorState: this.contentState(value)
});
if (nextProps.required && value.trim()) {
this.setState({
isValid: true
});
}
}
}
classNames() {
if (this.state.isValid) {
return 'form-group';
} else {
return 'form-group has-error';
}
}
focus() {
this.input.focus();
}
onEditorStateChange(editorState) {
this.setState({
editorState
}, ()=> {
let data = {
target: {
value: draftToHtml(convertToRaw(editorState.getCurrentContent()))
}
}
this.props.onChange(data);
});
};
render() {
const { editorState } = this.state;
return (
<div className={`${this.props.className} ` + this.classNames() }>
<ShowIf condition={this.props.label != ''}>
<label>
{ this.props.label }
<ShowIf condition={this.props.required}>
<span className="text-required"> *</span>
</ShowIf>
</label>
</ShowIf>
<ShowIf condition={this.props.heading != null}>
<this.props.heading/>
</ShowIf>
<Editor
editorState={editorState}
ref={(input) => {this.input = input}}
wrapperClassName="demo-wrapper"
editorClassName={this.props.inputClassName}
onEditorStateChange={this.onEditorStateChange.bind(this)}
style={{width: this.props.width, height: this.props.height}}
rows={this.props.rows}
maxLength={this.props.maxLength}
toolbar={{
...this.props.toolbar,
image: {
...this.props.toolbar.image,
uploadCallback: this.props.uploadCallback
}
}}
/>
<ShowIf condition={!this.state.isValid}>
<span className="help-block">{this.state.validationText}</span>
</ShowIf>
</div>
);
}
}
RichTextarea.propTypes = {
rows: PropTypes.number,
type: PropTypes.string,
label: PropTypes.string,
onChange: PropTypes.func,
placeholder: PropTypes.string,
maxLength: PropTypes.number,
width: PropTypes.string,
height: PropTypes.string,
heading: PropTypes.any,
toolbar: PropTypes.object
}
RichTextarea.defaultProps = {
rows: 10,
type: 'text',
className: 'input-group',
inputClassName: '',
label: '',
onChange: function() {
console.log('Need to assign onChange method');
},
placeholder: null,
required: false,
maxLength: 255,
name:'',
validationText: 'error',
width: '100%',
height: 'auto',
heading: null,
toolbar: {
options: ['inline', 'list', 'textAlign', 'link', 'embedded', 'image', 'blockType', 'fontSize', 'fontFamily'],
embedded: {
defaultSize: {
height: 400,
width: 'auto',
},
alignmentEnabled: true
},
image: {
urlEnabled: true,
uploadEnabled: true,
alignmentEnabled: true,
uploadCallback: function() {
},
inputAccept: 'image/gif,image/jpeg,image/jpg,image/png,image/svg',
alt: { present: false, mandatory: false },
defaultSize: {
height: 'auto',
width: 'auto',
},
}
}
}
export default RichTextarea;