Reputation: 1616
I've created a working Gutenberg Block with Create Guten Block (https://github.com/ahmadawais/create-guten-block). Currently it's only working with inline-styles, but as a requirement I have to avoid them.
Therefore I want to create a post/page stylesheet when the post is saved including the style settings for my blocks (for example background-color, color, font-size...)
My block's current save function (block.js)
save: function( props ) {
const { attributes: { typetext, infotext, linktext, background_color, background_button_color, text_color, text_color_button }} = props;
return (
<div id="cgb-infoblock" className="cgb-infoblock">
<div className="cgb-infoblock-body" style={{
backgroundColor: background_color,
color: text_color,
}}>
<div className="cgb-infoblock-type">
<p>
<span className="cgb-infoblock-icon"><i>i</i></span>
{ typetext && !! typetext.length && (
<RichText.Content
tagName="span"
className={ classnames(
'cgb-infoblock-type-text'
) }
style={ {
color: text_color
} }
value={ typetext }
/>
)}
</p>
</div>
<div className="cgb-infoblock-text">
{ infotext && !! infotext.length && (
<RichText.Content
tagName="p"
style={ {
color: text_color
} }
value={ infotext }
/>
)}
</div>
</div>
<div className="cgb-infoblock-button" style={{
backgroundColor: background_button_color,
color: text_color_button,
}}>
{ linktext && !! linktext.length && (
<RichText.Content
tagName="p"
style={ {
color: text_color_button
} }
value={ linktext }
/>
)}
</div>
</div>
);
},
The best solution would be some sort of stylesheet generation for a whole page/post with all settings from all blocks.
Best way would be if the stylesheet generation is happening on page save, but it would be also ok if it is happening on page-load. Since those posts are not going to be large, the performance shouldn't be that much of a problem.
Upvotes: 2
Views: 1229
Reputation: 1616
So after digging around I've figured it out myself. Just in case someone else got this problem here's the solution:
First of all, attributes have to be defined in registerBlockType
function
registerBlockType( 'cgb/your-block-type', {
title: __( 'Your Block Name' ),
icon: 'shield',
category: 'maybe-a-category',
keywords: [
__( 'some keywords' ),
],
attributes: {
background_color: {
type: 'string',
default: 'default' //we will use the "default"-value later
},
},
So now Wordpress knows which attributes you wanna save. Problem now, as long as the "default" value is not overwritten, Wordpress won't save the value into the block object's attributes.
To solve this we'll use the save
function from registerBlockType
.
(Quick note on this: This will not trigger the default value for the editor widget, so you allways have to change your background_color's value to see it the first time you insert your widget into gutenberg editor. To fix this, use saveDefaultValue(this.props)
right at the beginning of your render()
function.)
save: function( props ) {
saveDefaultValues(props);
const { attributes: {background_color}} = props;
return (
//... here's your html that's beeing saved
);
},
function saveDefaultValues(props) {
if(props.attributes.background_color === 'default'){
props.attributes.background_color = '#f1f6fb';
}
}
With this we are forcing wordpress to save our default value. Pretty sure there's a better solution for this, but since I just started with react / Gutenberg, this is the only thing that got it working for me.
Ok, now we can save our Attributes into the Block-object.
Now we wanna create our dynamic stylesheet.
For this we are creating a new .php file in the following directory /plugin-dir/src/
since we are using create-guten-block. The name doesn't matter, but I named it the same way like my stylesheet. `gutenberg-styles.css.php``
The gutenberg-styles.css.php
will later create a gutenberg-styles.css
file, everytime someone is visiting the post. But first we are looking into the plugin.php
file.
Add the following code:
function create_dynamic_gutenberg_stylesheet() {
global $post;
require_once plugin_dir_path( __FILE__ ) . 'src/gutenberg-styles.css.php';
wp_enqueue_style('cgb/gutenberg-styles', plugins_url( 'src/gutenberg-styles.css', __FILE__ ));
}
add_action('wp_head', 'create_dynamic_gutenberg_stylesheet', 5, 0);
This code accesses the global $post
variable, we need it to get all the gutenberg-blocks from the current visited post.
After that we require our own gutenberg-styles.css.php
which will automatically create our stylesheet, which will be enqueued in the next line.
Now hook it up to wp_head
(you could probably hook it up to wordpress save action as well, but you will have to do more work for enqueuing the stylesheet)
Finally a look into our gutenberg-styles.css.php
:
$styleSheetPath = plugin_dir_path( __FILE__ ) . 'gutenberg-styles.css';
$styleSheet = '';
$blocks = parse_blocks($post->post_content);
//loop over all blocks and create styles
foreach($blocks as $block) {
$blockType = $block['blockName'];
$blockAttributes = $block['attrs']; //these are the attributes we've forced to saved in our block's save function
//switch case so you can target different blocks
switch ($blockType) {
case 'cgb/your-block-type':
$styleSheet .= '.your-block-class {'.PHP_EOL
$styleSheet .= 'background-color: '.$blockAttributes['background_color'].';'.PHP_EOL
$styleSheet .= '}'.PHP_EOL
break;
}
}
file_put_contents($styleSheetPath, $styleSheet); //write css styles to stylesheet (creates file if it not exists)
I've added PHP_EOL
at each line to generate line breaks, you don't have to do this.
But now you can visit a page with your custom block and will see the gutenberg-styles.css
is loaded and applied to your blocks.
Upvotes: 3