Draft-js: Recommended way to create styles on-the-fly?

Created on 23 Feb 2016  Â·  13Comments  Â·  Source: facebook/draft-js

In a previous project similar to Draft.js I used JSS to create a dynamic stylesheet that I could manage classes and styles in real-time. Primarily for things like changing text color to a user-selected color, or changing font-size to something the user selects. This allowed for a lot of flexibility, but also meant that the styles didn’t have to be created up front. They were created on-the-fly, as the user selected them.

Is there a recommended way to create classes and/or styles (mostly inline) on-the-fly and applying to the selection?

enhancement

Most helpful comment

It's possible to create a color picker. Here is an example https://webdeveloperpr.github.io/draft-js-color-picker/

All 13 comments

Take a look at the "Color" editor example. This example should give you an idea of how inline styles can be named and defined via the customStyleMap prop. In the "Color" example, the styles are treated as mutually exclusive (since it's font color) but inline styles do not have to be mutually exclusive in this way.

For instance, we could include something like this within the customStyleMap with color values in it:

small: {
  fontSize: '8px',
},
medium: {
  fontSize: '12px',
},
large: {
  fontSize: '16px',
},

Then, by using RichUtil, you could add these styles to ranges as needed. Characters could then have styles like OrderedSet(['small', 'red']) or OrderedSet(['large', 'blue']).

At render time, these style values will be merged. In this way, you can define distinct inline styles and let React (more specifically, DraftEditorLeaf) worry about merging the values together.

Does this help?

I think I’ve got that part figured out thus far, and it’s working wonderfully. My question is more about the CSS property values themselves, and whether or not they can be dynamic.

Here’s the thing: I’m working with many hundreds of font styles (~700) that each require their own CSS properties (font-family, font-style and font-weight). I _could_ create the styles for every possible font file that _may_ be loaded up front, but that would clearly be a lot more data for the user to load than is really necessary.

So, I’m wondering if there is a way to make the _value_ of the CSS property dynamic, and only set when requested by the user?

For instance, say I have a select menu with 100 different fonts in it that the user can choose from. To avoid preloading 100 fonts worth of CSS classes/properties, I’d like to only create and apply them when requested. So when selecting “Fancy Font Number 5” in the menu I need to:

  • Create the CSS class and properties (font-family, font-style and font-weight);
  • Load the font file with a Webpack require; and
  • Apply the CSS class to the selection.

Can I add styles to the customStyleMap object _after_ the Editor is already mounted?

For what it’s worth, I’ve been working on a proprietary tool very much like Draft.js for the last 6 months or so using Rangy, Scribe and JSS. This is what I currently do when the user selects a font to load:

loadFont = () => {
    const {
        selectedFamily,
        selectedStyle,
        sheet
    } = this.props;

    // Stop here if user hasn’t selected a style yet
    if (!selectedFamily || selectedFamily === null || selectedStyle === null) return false;

    // Create the CSS based on the product data
    const fontStyles = {
        'font-family': selectedStyle.value,
        'font-style': selectedStyle.style,
        'font-weight': selectedStyle.weight
    };

    // Create CSS class
    const className = fontClassName(selectedFamily.label, selectedStyle.id);

    // Add the CSS to the JSS sheet
    const theRule = sheet.addRule(`.${className}`, fontStyles, { named: false });

    global.scribe.transactionManager.run(() => {
        // Create the CSS class and inline styles based on the font
        // parameters passed in from the JSON
        theRangyClass = rangy.createClassApplier(className, {
            applyToEditableOnly: true,
            tagNames: ['p'],
            useExistingElements: true
        });

        // Apply the class and styles to the selected text
        theRangyClass.applyToSelection();
    });

    // Load the font CSS and associated file
    require(`font/css/${selectedStyle.value}.css`);

    // Return the JSS generated className
    return theRule.className;
};

Can I add styles to the customStyleMap object after the Editor is already mounted?

You can define a new customStyleMap to pass in as the prop, though that won't currently trigger a re-render of the entire editor if the ContentState hasn't changed along with it.

What we could do is make customStyleMap an immutable Map (which we probably should have done anyway), then allow a full re-render if it changes so that the newly defined styles can be picked up. That way, when you want to load your fonts, once they are available you could create a new customStyleMap and pass it through.

That sounds nice.

What we could do is make customStyleMap an immutable Map (which we probably should have done anyway), then allow a full re-render if it changes so that the newly defined styles can be picked up. That way, when you want to load your fonts, once they are available you could create a new customStyleMap and pass it through.

so it means I could also show a color picker to select a wathever color ?

PR landed and fixed the issue, so closing this out.

@linzerui super super late response, but yes - it seems like you could achieve dynamic styles by updating the customStyleMap and referencing the class name you use in customStyleMap

@linzerui were you able to implement the colour picker ?

It's possible to create a color picker. Here is an example https://webdeveloperpr.github.io/draft-js-color-picker/

You can also create custom styles with this package https://www.npmjs.com/package/draft-js-custom-styles

@webdeveloperpr, I already stumbled upon both of these, and used it (http://bit.ly/poetry-editor) (and spent a lot of time understanding it, because I'm new to draft-js), needless to stay star-ed 'em! Kudos to you! đź’›.

@webdeveloperpr hi, did you use your package to make this color-picker ? I'm trying to figure it out :| Do you have code for draft-js-color-picker example?

Was this page helpful?
0 / 5 - 0 ratings