Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 13d2a76

Browse files
Merge pull request draft-js-plugins#960 from draft-js-plugins/updating-decorators
Add missing decorators to editorState when props update
2 parents bc9887c + f9948a5 commit 13d2a76

File tree

6 files changed

+73
-76
lines changed

6 files changed

+73
-76
lines changed

FAQ.md

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,5 @@
11
# Frequently Asked Questions
22

3-
## How to reset the content?
4-
5-
Since the decorators are stored in the EditorState it's important to not reset
6-
the complete EditorState. The proper way is to reset the ContentState which is
7-
part of the EditorState. In addition this ensures proper undo/redo behavior.
8-
9-
Right:
10-
```js
11-
import { EditorState, ContentState } from 'draft-js';
12-
13-
const editorState = EditorState.push(this.state.editorState, ContentState.createFromText(''));
14-
this.setState({ editorState });
15-
```
16-
17-
Wrong:
18-
```js
19-
import { EditorState } from 'draft-js';
20-
21-
this.setState({ editorState: EditorState.createEmpty() })
22-
```
23-
24-
## Why are mentions broken after using `convertFromRaw` and throwing an error?
25-
26-
__Please Note: this has been fixed in the beta version, from now on you can use a plain array for your mention suggestions__
27-
28-
We design the API to accept an Immutable Map for a Mention. After saving your data structure to the server and using `convertFromRaw`, the mentions in there are plain objects. I (Nik) believe this is a flaw in our design and the mention data should be a plain object. Hint: we might fix this with v2.0.0 of the mentions plugin.
29-
30-
What you can do now is fixing the datastructure before converting it:
31-
32-
```JS
33-
import { fromJS} from 'immutable';
34-
import forEach from 'lodash/forEach';
35-
36-
forEach(rawContent.entityMap, function(value, key) {
37-
value.data.mention = fromJS(value.data.mention)
38-
})
39-
40-
const contentState = Draft.convertFromRaw(rawContent)
41-
const editorState = Draft.EditorState.createWithContent(contentState)
42-
```
43-
443
## Why is there no Popover for Mentions/Emoji plugin?
454

465
The MentionSuggestions/EmojiSuggestions component is internally connected to the

draft-js-plugins-editor/CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
All notable changes to this project will be documented in this file.
44
This project adheres to [Semantic Versioning](http://semver.org/).
55

6-
## To Be Released
7-
8-
### Added
6+
## 2.0.2
7+
- Automatically update decoratorless editorState upon props update
98

9+
## 2.0.1
1010
- blockStyleFn returns '' instead of false
1111
- `handleKeyCommand` now receives the arguments `(command, editorState, pluginFunctions)`
1212
- `handlePastedText` now receives the arguments `(text, html, editorState, pluginFunctions)`

draft-js-plugins-editor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "draft-js-plugins-editor",
3-
"version": "2.0.1",
3+
"version": "2.0.2",
44
"description": "Editor for DraftJS Plugins",
55
"author": {
66
"name": "Nik Graf",

draft-js-plugins-editor/src/Editor/__test__/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ class TestEditor extends Component {
1515
this.state.editorState = createEditorStateWithText(this.props.text);
1616
}
1717

18+
componentWillReceiveProps(props) {
19+
this.setState({
20+
editorState: createEditorStateWithText(props.text),
21+
});
22+
}
23+
1824
onChange = (editorState) => {
1925
this.setState({
2026
editorState,
@@ -665,5 +671,20 @@ describe('Editor', () => {
665671
expect(customPluginDecorator).has.been.called();
666672
expect(decoratorStrategy).has.been.called();
667673
});
674+
675+
it('reassigns decorators to editorState when props are updated with naked editorState', (done) => {
676+
const props = { plugins, text };
677+
const comp = mount(<TestEditor {...props} />);
678+
679+
const decoratorNumber = comp.state('editorState').getDecorator().decorators.size;
680+
681+
setTimeout(() => {
682+
const newText = 'Yoyoyoyo dude';
683+
comp.setProps({ text: newText });
684+
expect(comp.state('editorState').getDecorator().decorators.size).to.eq(decoratorNumber);
685+
expect(comp.state('editorState').getCurrentContent().getPlainText()).to.eq(newText);
686+
done();
687+
}, 100);
688+
});
668689
});
669690
});

draft-js-plugins-editor/src/Editor/index.js

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
import React, { Component } from 'react';
33
import PropTypes from 'prop-types';
44
import {
5-
Editor,
65
EditorState,
6+
Editor,
77
DefaultDraftBlockRenderMap,
88
} from 'draft-js';
9-
import { List, Map } from 'immutable';
10-
import MultiDecorator from './MultiDecorator';
11-
import createCompositeDecorator from './createCompositeDecorator';
12-
import moveSelectionToEnd from './moveSelectionToEnd';
9+
import { Map } from 'immutable';
1310
import proxies from './proxies';
11+
import moveSelectionToEnd from './moveSelectionToEnd';
12+
import resolveDecorators from './resolveDecorators';
1413
import * as defaultKeyBindingPlugin from './defaultKeyBindingPlugin';
1514

1615
/**
@@ -25,6 +24,7 @@ class PluginEditor extends Component {
2524
defaultKeyBindings: PropTypes.bool,
2625
defaultBlockRenderMap: PropTypes.bool,
2726
customStyleMap: PropTypes.object,
27+
// eslint-disable-next-line react/no-unused-prop-types
2828
decorators: PropTypes.array,
2929
};
3030

@@ -56,22 +56,23 @@ class PluginEditor extends Component {
5656
}
5757

5858
componentWillMount() {
59-
const decorators = this.resolveDecorators();
60-
const compositeDecorator = createCompositeDecorator(
61-
decorators.filter((decorator) => !this.decoratorIsCustom(decorator)),
62-
this.getEditorState,
63-
this.onChange);
59+
const decorator = resolveDecorators(this.props, this.getEditorState, this.onChange);
6460

65-
const customDecorators = decorators
66-
.filter((decorator) => this.decoratorIsCustom(decorator));
67-
68-
const multiDecorator = new MultiDecorator(
69-
customDecorators.push(compositeDecorator));
70-
71-
const editorState = EditorState.set(this.props.editorState, { decorator: multiDecorator });
61+
const editorState = EditorState.set(this.props.editorState, { decorator });
7262
this.onChange(moveSelectionToEnd(editorState));
7363
}
7464

65+
componentWillReceiveProps(next) {
66+
if (
67+
this.props.editorState.getDecorator() !== null &&
68+
this.props.editorState.getDecorator() !== next.editorState.getDecorator()
69+
) {
70+
const decorator = this.props.editorState.getDecorator();
71+
const editorState = EditorState.set(next.editorState, { decorator });
72+
this.onChange(moveSelectionToEnd(editorState));
73+
}
74+
}
75+
7576
componentWillUnmount() {
7677
this.resolvePlugins().forEach((plugin) => {
7778
if (plugin.willUnmount) {
@@ -239,20 +240,6 @@ class PluginEditor extends Component {
239240
return plugins;
240241
};
241242

242-
resolveDecorators = () => {
243-
const { decorators, plugins } = this.props;
244-
return List([{ decorators }, ...plugins])
245-
.filter((plugin) => plugin.decorators !== undefined)
246-
.flatMap((plugin) => plugin.decorators);
247-
};
248-
249-
// Return true if decorator implements the DraftDecoratorType interface
250-
// @see https://github.com/facebook/draft-js/blob/master/src/model/decorators/DraftDecoratorType.js
251-
decoratorIsCustom = (decorator) => typeof decorator.getDecorations === 'function' &&
252-
typeof decorator.getComponentForKey === 'function' &&
253-
typeof decorator.getPropsForKey === 'function';
254-
255-
256243
resolveCustomStyleMap = () => (
257244
this.props.plugins
258245
.filter((plug) => plug.customStyleMap !== undefined)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { List } from 'immutable';
2+
import createCompositeDecorator from './createCompositeDecorator';
3+
import MultiDecorator from './MultiDecorator';
4+
5+
// Return true if decorator implements the DraftDecoratorType interface
6+
// @see https://github.com/facebook/draft-js/blob/master/src/model/decorators/DraftDecoratorType.js
7+
const decoratorIsCustom = (decorator) => typeof decorator.getDecorations === 'function' &&
8+
typeof decorator.getComponentForKey === 'function' &&
9+
typeof decorator.getPropsForKey === 'function';
10+
11+
12+
const getDecoratorsFromProps = ({ decorators, plugins }) => List(
13+
[{ decorators }, ...plugins]
14+
).filter((plugin) => plugin.decorators !== undefined)
15+
.flatMap((plugin) => plugin.decorators);
16+
17+
const resolveDecorators = (props, getEditorState, onChange) => {
18+
const decorators = getDecoratorsFromProps(props);
19+
const compositeDecorator = createCompositeDecorator(
20+
decorators.filter((decorator) => !decoratorIsCustom(decorator)),
21+
getEditorState,
22+
onChange);
23+
24+
const customDecorators = decorators
25+
.filter((decorator) => decoratorIsCustom(decorator));
26+
27+
return new MultiDecorator(customDecorators.push(compositeDecorator));
28+
};
29+
30+
export default resolveDecorators;

0 commit comments

Comments
 (0)