With the new wordpress update there are some new properties that have been added to the core gutenberg blocks to make it easier for certain users to customize these blocks
In the image above you can see the example for the new looks of the quote block. For instance there is now the option to change the appearance of the typography as well as a new 'plain' option for the styles. I want to remove these options, but The only thing i have found so far is how to add extra properties nd how to remove the block entierly.
For the styles, i have found the hook to get the property, but I don't know how i can modify this so it doesn't show the "plain" option:
// hide "plain" opiton inside the style tab of the quote block.
const {
addFilter,
} = wp.hooks;
addFilter(
'blocks.registerBlockType',
'jsforwp-advgb/extend-quote-block',
extendBlockQuoteBlock
);
function extendBlockQuoteBlock( settings, name ) {
if ( !settings || !settings.supports ) {
return settings;
}
if ( 'core/quote' !== name ) return settings;
console.log( settings.styles );
return settings;
}
Block styles can be removed with unregisterBlockStyle(blockName, styleVariationName). There is no need extend or add a filter to the block registration, just use unregisterBlockStyle when the DOM is ready to prevent a race condition:
wp.domReady( function () {
wp.blocks.unregisterBlockStyle( 'core/quote', 'plain' );
} );
Ref: Block Editor Handbook / Reference Guides / Block API Reference / Styles
Update: Below is a screenshot showing the effect of running wp.blocks.unregisterBlockStyle( 'core/quote', 'plain' ) in the console.
If you wish to remove typography, it is different to block styles and is from the block supports API, which is done with addFilter and lodash assign to remove support for the features you dont want, eg:
wp.hooks.addFilter(
'blocks.registerBlockType',
'jsforwp-advgb/extend-quote-block',
extendBlockQuoteBlock
);
function extendBlockQuoteBlock(settings, name) {
if (name !== 'core/quote') {
return settings;
}
return lodash.assign({}, settings, {
supports: lodash.assign({}, settings.supports, {
typography: false,
}),
});
}
Related
Problem: I'm looking to expand our WordPress theme(s)/websites to make it easier for our communications team to create posts and pages by adding in Bootstrap rows and columns.
My idea is to create A custom Field type with a selection to add in rows and columns to fit our themes pages.
Has anyone done something like this? We are using Divi Builder but that is a bit complicated for average users and we are not in arush to create a whole new theme for our 30+ websites.
Or would I need to create a custom plugin for that? I'd rather not use a third party plugin for security reasons
So are you wanting output bootstrap markup in your default wordpress editor to make rows and columns etc?
Short answer is no, the wysiwyg editor is only really built for paragraphs, headings, quotes, horizontal rules, lists, images, inline formatting etc...
In order integrate bootstraps block layout markup would require some extra level of builder addon. Elementor definitely could do the job with some super customisation, even ACF flexible content would do it, and i think even WP Gutenberg can do this natively... but would require customisation to use bootstrap markup.
But if you wanted to attempt and utilise the standard wordpress editor (not Gutenberg editor) using the element dropdown (paragraph, headings etc by default).
You could try this, however I recommend loading the same front end bootstrap css into the wysiwyg editor so you can instantly see changes.
Please note this method below is risky as the user would need to understand how bootstraps row/column structure should be formatted. The probability of html markup going wrong is highly likely. Hence using an actual block element builder (like Elementor or ACF) would be a safer choice.
Anyway, see below example of how to customise standard wordpress wysiwyg editor dropdown for wrapping html tags around content.
First load the same front end bootstrap css into the wysiwyg editor...
// editor stylesheet (containing the front end css for the post content)
add_editor_style('dist/css/editor.css');
Now lets add the styleselect dropdown to our wysiwyg editor...
// add the style select dropdown to our wysiwyg editor
add_filter('mce_buttons_2', 'formatting_dropdown');
/**
* #link https://developer.wordpress.org/reference/hooks/mce_buttons_2
* #param $buttons
* #return mixed
*/
function formatting_dropdown($buttons) {
// global post object
global $post;
// if no post return param
if(!$post) return $buttons;
// switch case for post types or type to run this on (page/post)
switch ($post->post_type) {
case 'page':
case 'post';
// reveal the hidden “Styles” dropdown in the advanced toolbar
array_unshift($buttons,'styleselect');
return $buttons;
default;
return $buttons;
}
}
And then add your bootstrap formatting settings using this filter below...
// init filter for handling the style select options
add_filter('tiny_mce_before_init', 'formatting_dropdown_options');
/**
* #link https://developer.wordpress.org/reference/hooks/tiny_mce_before_init/
* #param $mceInit
* #return mixed
*/
function formatting_dropdown_options($mceInit) {
// global post
global $post;
// if no post return param
if(!$post) return $mceInit;
// switch case for post type (page/post)
switch ($post->post_type) {
case 'page':
case 'post';
// new style array
$style_formats = [
[
'title' => 'row',
'block' => 'div',
'classes' => 'row'
],
[
'title' => 'col',
'block' => 'div',
'classes' => 'col'
]
];
// bs5 breakpoints
$breakpoints = ['xs','sm','md','lg','xl','xxl'];
// bs5 column grid
$grid = 12;
// add bs5 column classes to $style_formats array
foreach ($breakpoints as $breakpoint) {
foreach (range(1, $grid) as $column) {
$style_formats[] = [
'title' => $breakpoint === 'xs' ? 'col-' . $column : 'col-' . $breakpoint . '-' . $column,
'block' => 'div',
'classes' => $breakpoint === 'xs' ? 'col-' . $column : 'col-' . $breakpoint . '-' . $column
]
}
}
// override style format with new style formats
$mceInit['style_formats'] = json_encode($style_formats);
// init array
return $mceInit;
break;
default;
// init array
return $mceInit;
}
}
I am developing a plugin for wordpress and I want to add the button to the header of gutenberg editor just like the one added by Elementor plugin "Edit with Elementor"
Can anyone guide me what should i do to achieve this... Thanks in Advance
I've checked Guternberg source code on header toolbar and unfortunately right now there's only not a beautiful solution possible. You can have 'custom' buttons but they are only done through calling registerPlugin with PluginSidebar component which creates sidebar and button appears on right side for pinned\starred sidebars (like Yoast SEO does).
Elementor does it this way: it subscribes to wp.data store changes and whenever something happens it injects it's button if it's not yet injected. Just because React rerenders DOM it may eventually wipe button out, so subscribing to changes is important so if it wipes out custom button js code just reinjects it.
Below is simplified ES5 code to inject a custom link\button or really any custom HTML into it (just as Elementor does).
// custom-link-in-toolbar.js
// wrapped into IIFE - to leave global space clean.
( function( window, wp ){
// just to keep it cleaner - we refer to our link by id for speed of lookup on DOM.
var link_id = 'Your_Super_Custom_Link';
// prepare our custom link's html.
var link_html = '<a id="' + link_id + '" class="components-button" href="#" >Custom Link</a>';
// check if gutenberg's editor root element is present.
var editorEl = document.getElementById( 'editor' );
if( !editorEl ){ // do nothing if there's no gutenberg root element on page.
return;
}
var unsubscribe = wp.data.subscribe( function () {
setTimeout( function () {
if ( !document.getElementById( link_id ) ) {
var toolbalEl = editorEl.querySelector( '.edit-post-header__toolbar' );
if( toolbalEl instanceof HTMLElement ){
toolbalEl.insertAdjacentHTML( 'beforeend', link_html );
}
}
}, 1 )
} );
// unsubscribe is a function - it's not used right now
// but in case you'll need to stop this link from being reappeared at any point you can just call unsubscribe();
} )( window, wp )
So create a js file in your theme or plugin and then link it this way:
add_action( 'enqueue_block_editor_assets', 'custom_link_injection_to_gutenberg_toolbar' );
function custom_link_injection_to_gutenberg_toolbar(){
// Here you can also check several conditions,
// for example if you want to add this link only on CPT you can
$screen= get_current_screen();
// and then
if ( 'cpt-name' === $screen->post_type ){
wp_enqueue_script( 'custom-link-in-toolbar', get_template_directory_uri() . '/assets/js/custom-link-in-toolbar.js', array(), '1.0', true );
}
}
Again this solution isn't perfect because we just inject our custom HTML into DOM which is managed by Gutenberg(React) but at this point it seems like the only way to achieve it, may be in future we'll have something like filters or hooks which will allow us to inject our custom components being rendered in toolbar but not yet.
Still Elementor does it this way. you can check it's code at
https://github.com/elementor/elementor/blob/master/assets/dev/js/admin/gutenberg.js
Now there is a slot for the Main dashboard button you can use that one
import { registerPlugin } from '#wordpress/plugins';
import {
__experimentalFullscreenModeClose as FullscreenModeClose,
__experimentalMainDashboardButton as MainDashboardButton,
} from '#wordpress/edit-post';
import { close,image } from '#wordpress/icons';
const MainDashboardButtonIconTest = () => (
<MainDashboardButton>
<FullscreenModeClose icon={ close } href="http://wordpress.org" />
<Button variant="primary" icon={image}>
My Button
</Button>
</MainDashboardButton>
);
registerPlugin( 'main-dashboard-button-icon-test', {
render: MainDashboardButtonIconTest,
} );
ref: https://developer.wordpress.org/block-editor/reference-guides/slotfills/main-dashboard-button/
I'm building a Wordpress plugin that relies on custom fields being enabled when registering a custom post type. I want to check if the custom-fields key exists (and is true) in supports in the post type object. However, when I call wp.data.select('core').getPostType('post-type'), it returns undefined. If I call it directly from the console, I get the post type object I expect, so I'm not sure why it isn't working in my code.
I've tried calling this from a few places.
E.g. When registering the plugin panel:
// Loading `wp.editPosts`, `wp.plugins`, etc. excluded for brevity.
const Component = () => {
const postType = wp.data.select('core/editor').getCurrentPostType();
const postTypeObj = wp.data.select('core').getPostType(postType);
if (postTypeObj.supports.hasOwnProperty('custom-fields')) {
return (
<PluginDocumentSettingPanel
name="my-plugin-name"
title={ __('My Plugin Title', 'pb') }
>
<MyPlugin/>
</PluginDocumentSettingPanel>
);
}
return;
};
registerPlugin('my-plugin-name', {
render: Component,
icon: '',
});
or within the plugin itself via withSelect:
// Loading `wp.compose`, `wp.data`, etc. excluded for brevity.
class MyPlugin extends React.Component {
constructor(props) {
super(props);
this.state = {
// I'll do something with this later on
postTypeObj: props.postTypeObj,
};
}
render() {
return (
<div></div>
);
}
}
export default compose([
withSelect(select => {
const {
getCurrentPostType,
} = select('core/editor');
const {
getPostType,
} = select('core');
return {
postTypeObj: getPostType(getCurrentPostType()),
}
}),
])(MyPlugin);
No matter where I call it, the post type object returns undefined.
I'm using the Gutenberg Plugin, version 6.5.0 and WordPress version 5.2.3.
Any help is appreciated.
Calling getCurrentPostType() will return e.g. post. You may not need to wrap it in getPostType too. Also, according to https://github.com/WordPress/gutenberg/issues/13555, you will need to “subscribe” (wp.data.subscribe) as this is an asynchronous call, and so will return null the first time you run it.
This is characteristic of anything from wp.data.select('core'), and of things built on top of it.
The issue is that react is making an ajax call to get the data. And, when the response comes back, that will trigger another render. So, if you've arranged things with that in mind, your code will run again (when the response arrives), and get a non-null result based on the response from the server which will have been stored for you by then.
Put different: initially things are blanks, and those blanks will get filled in.
(This is worth repeating, so please educate others about this issue.)
For those who needs this functionality under custom post type edit window, there are few requirements.
1. When registering custom post type make sure show_in_rest is set to true and supports array includes editor. This will enqueue required scripts.
Or you can manually enqueue them as follows:
function enable_gutenberg_on_custom_post_types( $hook ) {
global $current_screen;
// Load on certain post type
if ( 'product' !== $current_screen->post_type ) {
return;
}
/**
* Make the WP Screen object aware that this is a block editor page.
* Since custom blocks check whether the screen is_block_editor,
* this is required for custom blocks to be loaded.
* See wp_enqueue_registered_block_scripts_and_styles in wp-includes/script-loader.php
*/
$current_screen->is_block_editor( true );
/**
* Fires after block assets have been enqueued for the editing interface.
*
* Call `add_action` on any hook before 'admin_enqueue_scripts'.
*
* In the function call you supply, simply use `wp_enqueue_script` and
* `wp_enqueue_style` to add your functionality to the block editor.
*
* #since 5.0.0
*/
do_action( 'enqueue_block_editor_assets' );
}
add_action( 'admin_enqueue_scripts', 'enable_gutenberg_on_custom_post_types' );
2. you need to enqueue other scripts as well, i.e wp-data and wp-edit-posts:
wp_enqueue_script(
'my-custom-script',
PLUGIN_URL . 'dist/admin.js',
array( 'react', 'react-dom', 'wp-data', 'wp-edit-post' ),
'1.0.0',
false
);
Then in javascript:
window.wp.data.select('core').getEntityRecords( 'postType', 'post' )
Or using hook:
const posts = window.wp.data.useSelect((select) => {
return select('core').getEntityRecords('postType', 'product');
}, []);
In Gutenberg Editor, I try to modify the categories panel (the one on the right where I choose the categories my post will be placed into).
One should not be able to add a post to a category if that category has child-categories. As the categories are static, it'll be ok to use the category-id.
My idea was to use the enqueue_block_editor_assets and add some javascript to disable the checkbox via the ID of the element.
This does not work, the element could not be found :-(
This is my unfunctional code so far:
functions.php:
function gutenberg_enqueue()
{
wp_enqueue_script(
'gutenberg-additions-script',
get_stylesheet_directory_uri().'/gutenberg-additions.js',
array(), true, true
);
}
add_action('enqueue_block_editor_assets', 'gutenberg_enqueue', 999);
(I use get_stylesheet_directory_uri(), because I am in a child theme)
gutenberg-additions.js:
window.onload = function () {
var cat1 = document.getElementById('editor-post-taxonomies-hierarchical-term-1');
if (cat1 != null) {
cat1.disabled = true;
}
Welcome to Stackoverflow. There is an example about that in the gutenberg github directory. It is written in the old es5 syntax, but should easily be transferrable to esnext. It uses the editor.PostTaxonomyType filter to edit the taxonomies component.
var el = wp.element.createElement;
function customizeProductTypeSelector( OriginalComponent ) {
return function( props ) {
if ( props.slug === 'product-type' ) {
return el(
'div',
{},
'Product Type Selector'
);
} else {
return el(
OriginalComponent,
props
);
}
}
};
wp.hooks.addFilter(
'editor.PostTaxonomyType',
'my-custom-plugin',
customizeProductTypeSelector
);
If you need more information, also read the comments on this github issue.
When I add gallery in post the default value of link attribute is none. I want media (or mediafile, I don't know how is right) value as default. Documentation says me nothing.
Add this to your gutenberg script:
wp.hooks.addFilter(
'blocks.registerBlockType',
'my-theme/modify-linkTo-default',
function (settings, name) {
if (name !== 'core/gallery') {
return settings;
}
settings.attributes.linkTo.default = 'media';
return settings;
}
);