I was deep into Draft a while back, and there are some downsides to it though. It's document model is flat, which makes it hard to model nested structures like tables, captions, etc. It also treats a lot of the built-in logic in privileged ways which makes it hard to override and add custom logic. And generally the API and docs are fairly convoluted to use and understand.
If anyone is interested in composing complex editors in React/Immutable, you might be interested in a library I've been working on called Slate:
https://github.com/ianstormtaylor/slate
Unlike most of the other editors, its goal is to not have opinions out of the box. If you're going for just basic WYSIWYG then it's probably not for you, but if you're trying for more advanced editing experiences I think that flexibility is critical.
Anyways, awesome work! I just wanted to add another perspective.
I've built and am maintaining a rich text editor that is a lot like Gmail's except it also supports dynamic variables, snippet insertion, and a few other things like that. Nested content hasn't been a concern for me, so DraftJS has been pleasant for the most part. Using Immutable for core state makes my life so much easier.
But I do agree with your assessment that Draft's API and docs are lacking, and some of the design decisions are a bit odd. Doing relatively simple operations can require quite a few more steps than you would expect, meaning I had to implement a lot of helpers (that you think would be included) myself. Slate's Transform API looks a lot more capable and straightforward out of the box.
HTML serialization, something you would expect to be part of the core library, only has a half-assed implementation that isn't customizable and that doesn't handle anything more than anchor tags.. so you have to install a third-party library to do it.
Just one question: if you can have nested blocks, do you really even need marks? Are they just there for convenience?
> If you can have nested blocks, do you really even need marks? Are they just there for convenience?
Interesting question!
It depends slightly on your use case, but I think for most of the "rich text editing" use cases, you'll probably want them.
They're beneficial in that they have separate semantics to inline nodes in the tree, since they aren't nested. Such that you can apply them in any order, and the JSON data structure is the same. This is useful because you don't have to worry about ordering when doing things like bold(italic(strikethrough(comment(TEXT)))). Which is usually simpler for users to understand, and simpler to work with in code anyways.
The inline nodes are only really useful for what you'd model in HTML as `display: inline-block`, for things that aren't really running "text" but can appear in the middle of the document, like inline images, latex, etc.
But if you're able to avoid inline nodes altogether, it's easiest to model things as blocks and marks.
This has me thinking about whether it's possible to get rid of "inline" nodes though, that's interesting.
For super simple WYSIWYG editing, like I mentioned, you're not going to want to use Slate. (Or maybe Draft either.)
Slate is designed for much more advanced use cases. Things like building wiki tools, or chat tools, or anything where the editing experience itself is a significant enough portion of your product that you want total control over it, and don't want to be constrained by the opinions that most editing frameworks bake into their core libraries.
I'd maybe call this "an" approach, rather than the 'right' approach :)
Already, prosemirror has provided a solid alternative, with things like custom-schemas, which ensure we're no longer in contenteditable-copy/paste hell. There's substance.io and quilljs as well.
Any of these could be the right approach for a particular CMS problem.
I did not said only right approach :)
Here's some of the problems:
- You can accidentally "select" the text of the buttons
- changing the style of the text causes selection to flicker
- clicking outside a paragraph area causes the selection to flicker (instead of moving the cursor)
- many of the menus don't collapse automatically and they overlap each other
- the site layout just breaks when the page width is too narrow (may be more of a website problem)
All of these are very common problems with web technology, working around them makes the difference between "good" and "acceptable".
It's something I don't often see added to buttons, but it is a huge benefit for any app-like layout.
Plus, the development speed is good, but sloppy. Their official React documentation starts with something they forgot to change when they copy-pasted it from react-highcharts:
https://www.froala.com/wysiwyg-editor/docs/framework-plugins...
I've been using https://github.com/ianstormtaylor/slate instead, which uses a similar architecture but has inline blocks. It's not quite as fully-baked as Draft.js yet though.
I tried to reposition the cursor to no avail (the whole edit area loses and regains focus on each tap).
Also, I can't delete stuff (backspace does nothing).
Edit: at this point I just quit trying.
I've been tinkering with Draft off and on for quite some time and I love how powerful it is, however documentation was rather lacking in some areas and this project would definitely help me understand some of the things about Draft.
Too bad there's still only a workaround for block styles (as in setting "style" prop on a whole block instead of using setBlockData method).
Not sure if this is a bug, but if I set a specific font size, it doesn't attach any kind of unit. For example, if I select 18, it doesn't convert that to 18px or 18em...just "18":
<span style="font-size: 18;">This is some text.</span>
I believe that's not valid css.
Nice idea, but functionally not quite there yet.
A more noticeable thing is that if you select some text and then Bold / Italics / Underscore, etc. there is a flash where the text appears to be no selected and then becomes selected again.
Given this is React, my guess of what is going on is that the rich text is redrawn when these buttons are pressed (and perhaps even on each keystroke) and the selection has to be re-applied in code.
Perhaps they can improve this, but this is why I think it's important to stay away from high level frameworks for doing low-level things like text editing. Use your high level framework for application architecture and all that good stuff, but when something has to be fast, drop down to the lowest level you have.
I want to be able to render email templates and let clients tweak them before they gets sent. Currently trying to get Froala to work with webpack.
Edit: Someone beat me to it, but being 2/6 of the early comments shows that they are important!
(A requirement on the modern web, since you don't want to edit a file only to find out that your version was overwritten by another person who happened to be editing at the same time).
It can be made collaborative. Depends on how you integrate it in your application.