<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ DraftJS - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ DraftJS - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 20 May 2026 16:00:20 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/draftjs/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to create ordered and unordered lists in Draft.js with a shortcut ]]>
                </title>
                <description>
                    <![CDATA[ By Andrey Semin We at Propeller have encountered many differences between Draft.js and popular text editors. We also found some issues like controlling list depth and multiline items in lists. The biggest difference is the inability to use shortcuts ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-ordered-and-unordered-lists-in-draft-js-with-a-shortcut-5de34a1a570f/</link>
                <guid isPermaLink="false">66c351401283974fd2bb0794</guid>
                
                    <category>
                        <![CDATA[ DraftJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 14 Nov 2018 17:40:25 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*CrE6mvHFmfzE8Nzz" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Andrey Semin</p>
<p>We at <a target="_blank" href="https://www.propellercrm.com/">Propeller</a> have encountered many differences between Draft.js and popular text editors. We also found some issues like controlling list depth and multiline items in lists. The biggest difference is the inability to use shortcuts to start a list by default. Surprisingly enough you need to implement this logic yourself.</p>
<p>As always, there is a <a target="_blank" href="https://www.npmjs.com/package/draft-js-list-shortcut-plugin">plugin</a> available to add support for the shortcuts you use. I also want to refer to <a target="_blank" href="https://github.com/icelab/draft-js-autolist-plugin">draft-js-autolist-plugin</a> as a source of inspiration. For some reason, this plugin didn’t work when we tried it. So we’ve come up with our own solution which is now presented in this post.</p>
<h3 id="heading-the-problem">The problem</h3>
<p>Open Google Docs, Word365, or whatever editor you use. Try to type <code>*</code> and then type <code>space</code>. Boom! You’ve started an unordered list. Nice feature to have, right?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*2mOm_bMFavV3jy2g3a-wvA.gif" alt="Image" width="618" height="288" loading="lazy"></p>
<p>If we try the exact same trick with the default Draft.js configuration, we will get nothing but plain text.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ExCt2l6cP0BUhRjq036IKg.gif" alt="Image" width="600" height="196" loading="lazy"></p>
<p>Let’s change it!</p>
<h3 id="heading-solution">Solution</h3>
<p>To implement this feature, we need to keep track of the last three pressed buttons. Why three? Well, that’s because the longest character combination we need to support is <code>1. + space</code> which is exactly three presses.</p>
<p>To start, let’s implement the logic to store these presses. Here we would use a simple array named <code>history</code>. This array will store the value of the key that was pressed. We definitely don’t want to process any key presses with modifiers like <code>shift</code>, <code>alt</code> and so on. We can use Draft.js built-in<code>KeyBindingUtil.hasCommandModifier</code> function to perform the check for any modifier.</p>
<p>Draft.js exposes a <code>keyDown</code> event for us in the <code>keyBindingFn</code> prop function. We are going to check if we need to start a list here. If so, we need to return a so called<code>DraftEditorCommand</code>, which is a string. Also, to benefit from OS-level commands we need to add a <code>getDefaultKeyBinding</code> function call as a fall-through case.</p>
<p>We need to check if the currently pressed key is a <code>space</code>. If so we would run our checks against the <code>history</code> array. We check if we have a suitable set of previously pressed keys — <code>*</code> for an unordered list and <code>1.</code> for an ordered one. If we find a match, we return a command(string) to be processed later.</p>
<p>Now we need to implement the <code>handleKeyCommand</code> prop function and pass it to the editor. The logic is pretty simple. If we get one of our custom commands, we check if we should start a list on the current block. So here is a skeleton of the <code>handleKeyCommand</code> function.</p>
<p>To check if we are good to start a list, we check if the currently selected block satisfies all three of the following rules:</p>
<ul>
<li>The block type is <code>unstyled</code></li>
<li>The block has a <code>depth</code> of 0</li>
<li>the block has <code>*</code> or <code>1.</code> as a text</li>
</ul>
<p>Let’s wrap it up with the code:</p>
<p>Now we’re able to catch the exact case where Draft.js needs to start a list! Now it’s a time to implement the <code>startList</code> function.</p>
<p>First of all, we need to map our custom commands to a particular list style. This means we need to start an unordered list for the <code>start-unoredered-list</code> command.</p>
<p>We start an ordered list for the <code>start-ordered-list</code> command. Next, we need to update the styling of the block to the selected type. To do it we would use the <code>toggleBlockType</code> function of <code>RichUtils</code> module, which comes as a part of Draft.js.</p>
<p>Next we need to replace the shortcut text we’ve entered with an empty string. To do it we need to call the <code>replaceText</code> method of the <code>Modifier</code> module. This method requires a selection range to determine what should be replaced. We need to get the selection out of the block and update it to have <code>focusOffset</code> value equal to block length. This combination means we want to replace the whole text we’ve entered.</p>
<p>Great! Now we need to update our local editor state with the new state we get from the <code>startList</code> function. So let’s bring it all together!</p>
<p>OK! We’re almost done! But there is one more moment we need to handle. In some cases when one of our custom commands fire, we should not start a list based on the output of the <code>shouldStartList</code> function. We need to process the insertion of the space manually.</p>
<p>For implementation details of the <code>getSelectedBlock</code> method, check out <a target="_blank" href="https://medium.com/p/800fb3a6714c">my previous post</a> on this Draft.js topic!</p>
<p>To do this we may want to use a method called <code>insertText</code> of the <code>Modifier</code> module. Obviously enough, it is used to build a new content state with the provided text inserted into it. As always, we need to provide the current content state, current selection state and the text we want to insert (a single space in our case).</p>
<p>We need to add a call to this function to our <code>handleKeyCommand</code> function. So here is the final version of it:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*KB28XT74Srehykb3VRSOyw.gif" alt="Image" width="594" height="270" loading="lazy">
<em>We’ve added support of lists shortcuts. Good work!</em></p>
<p>If you’ve read this post all the way through, you may also want to check out <a target="_blank" href="https://medium.com/p/800fb3a6714c">my previous post</a> about Draft.js enchantment. You may want to apply it to your project as well.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
