Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

From v2.1.0 wp.blocks.getBlockTypes() returns an empty Array #4848

Closed
1 of 2 tasks
unCommonsTeam opened this issue Feb 3, 2018 · 23 comments
Closed
1 of 2 tasks

From v2.1.0 wp.blocks.getBlockTypes() returns an empty Array #4848

unCommonsTeam opened this issue Feb 3, 2018 · 23 comments
Labels
[Feature] Blocks Overall functionality of blocks [Feature] Extensibility The ability to extend blocks or the editing experience [Status] Not Implemented Issue/PR we will (likely) not implement. [Type] Bug An existing feature does not function as intended

Comments

@unCommonsTeam
Copy link

Issue Overview

Gutenberg Version: 2.1.0
With this version the function wp.blocks.getBlockTypes() returns an empty Array.

Steps to Reproduce (for bugs)

  1. Add a js script after the Gutenberg's wp-blocks script
  2. Add in your script the following code:
    console.log(wp.blocks.getBlockTypes());
  3. Open a post using Gutenberg editor
  4. Check the Console Log

Expected Behavior

The returned Array should be so:

0: Object { name: "core/shortcode", title: "Shortcode", description: "A shortcode is a WordPress-specific code snippet that is written between square brackets as [shortcode]. ", … }
1: Object { name: "core/image", title: "Image", description: "Worth a thousand words.", … }
2: Object { name: "core/gallery", title: "Gallery", description: "Image galleries are a great way to share groups of pictures on your site.", … }
3: Object { name: "core/heading", title: "Heading", description: "Search engines use the headings to index the structure and content of your web pages.", … }
....
....

Note: tested on v2.0.0

Current Behavior

The Array is empty instead:
Array[]
Note: tested on v2.1.0

Possible Solution

Probably there is a different way to call wp.blocks.getBlockTypes()

Todos

  • Tests
  • Documentation
@youknowriad
Copy link
Contributor

There's no different way, you're probably calling this function too soon. The core block registration has been slightly delayed to allow plugin authors to register registration hooks.

These delays and hooks are still being optimized, so this might change slightly in the future.

@unCommonsTeam
Copy link
Author

Hello youknowriad,

thank you for your fast reply!

I have enqueued the js so:

add_action( 'enqueue_block_editor_assets', 'my_function' );
function my_function() {
    wp_enqueue_script( 'my-script', 'path-to-my-script.js', array( 'wp-blocks' ) );
}

So the script is included after the the following file: /gutenberg/blocks/build/index.js

Do you have a solution for this problem?

Thanks!

@youknowriad
Copy link
Contributor

The blocks are now registered in the wp-editor module which means your script needs to run after that if you want to access the full block list.

@gziolo gziolo added [Feature] Blocks Overall functionality of blocks [Feature] Extensibility The ability to extend blocks or the editing experience labels Feb 3, 2018
@unCommonsTeam
Copy link
Author

unCommonsTeam commented Feb 3, 2018

Hi,

unfortunately adding the js with dependency on wp-editor I get this error:
Error: Minified React error #200; visit http://facebook.github.io/react/docs/error-decoder.html?invariant=200 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
Where 200 means -> Target container is not a DOM element.

Instead if I add my script in the footer adding true the final parameter of wp_enqueue_script() all seems to work for few seconds and then an error appears on the screen -> https://www.awesomescreenshot.com/image/3148981/e4b4acd328b6b0cff62bcf61ff994690

And the js error is:

TypeError: l is undefined
Stack trace:
value@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/editor/build/index.js?ver=1517658814:11:27019
h@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:130:362
beginWork@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:134:70
d@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:158:393
f@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:159:214
g@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:159:462
t@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:167:3
x@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:166:247
batchedUpdates@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:169:173
cc@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:26:56
jc@http://dev.uncommons.pro/lab/wp-content/plugins/gutenberg/vendor/react-dom.min.3583f8be.js:35:5
react-dom.min.3583f8be.js:162:310

So I explain better what I want to do.. so someone may bring me on the right way.

I simply have to disable a default block in the editor.. So for example something like this:
wp.blocks.unregisterBlockType( 'core/image' );

In the previous version (2.0.0) this function worked like a charm. With the acutal version how can I disable a default block in Gutenberg Editor?

Thanks in advance!

@unCommonsTeam
Copy link
Author

UPDATE

I discovered the cause of issue.

Here my setup

add_action( 'enqueue_block_editor_assets', 'my_function' );
function my_function() {
    wp_enqueue_script( 'my-script', 'path-to-my-script.js, array('wp-blocks', 'wp-element') );
}

In the script i added the window.onload function to wait all is loaded..

window.onload = function() {
...
my code
...
};

This setup works but appears an error in react when I unregister a block that is already added in the post.

For example if I have a post with an image block active and I unregister the core/image block I get the react error, probably because the editor can't render the image block already prensent in the post.

This is a problem because if a user have many posts built with Gutenberg and my plugin disable an important block, the user will always see the react error -> https://www.awesomescreenshot.com/image/3148981/e4b4acd328b6b0cff62bcf61ff994690

Is there a workaround for this issue?

Thanks

@gziolo
Copy link
Member

gziolo commented Feb 5, 2018

This setup works but appears an error in react when I unregister a block that is already added in the post.

This is a similar issue as described by @sheepzilla in #4699. We started exploring different ways of registering blocks to come up with a much reliable solution. You can see what has been proposed already in #2751. Code explorations are done in #4841. So the idea would be to have full control over which blocks are going to be registered on PHP side.

@aduth
Copy link
Member

aduth commented Apr 16, 2018

Possible regression of #5943? (cc @pento)

@jasonbahl
Copy link

I'm experiencing the same issue. . .not able to whitelist blocks.

Discussed in Slack here (https://wordpress.slack.com/archives/C02QB2JS7/p1523898765000445), but copying details to this issue for more visibility:

I'm enqueueing my script like so:

wp_enqueue_script(
  'oshpd-gutenblocks-editor-script',
  plugins_url( '/dist/js/blocks.build.js', __FILE__ ), 
  array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor' )
);

Then in my JS, I console log the registered blocks like so:

console.log( wp.blocks.getBlockTypes() );

This outputs an empty array.

If I do it from within a setTimeout, I get an array of 61 blocks logged:

setTimeout( () => {
  console.log( wp.blocks.getBlockTypes() );
}, 500 );

Then, if I set my unregisterBlockType code within a setTimeout, then console.log the blocks, I only get an array of 2 blocks logged to the console:

let allowedBlocks = [
  'core/paragraph',
  'core/image',
];

setTimeout( () => {

  wp.blocks.getBlockTypes().forEach( function( blockType ) {
    if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
      wp.blocks.unregisterBlockType( blockType.name );
    }
  } );

}, 500 );

setTimeout( () => {
  console.log( wp.blocks.getBlockTypes() );
}, 600 );

Looks good, right? I unregistered all but 2 blocks, and no my getBlockTypes() shows 2 blocks, so it seems like all is working now. . .well, it's not.

Now my console is littered with more errors and the editor becomes useless.

Attached is a GIF recording showing the experience with the above code in place.

gutenberg-whitelist-errors

From what I can tell, it appears to me that once a block is registered the DOM (or state tree?) gets built out with the knowledge of said registered blocks. Then, if you come along and unregister block(s), the DOM (or stat tree?) still assumes those block(s) exist and the editor at large no longer knows how to behave with those blocks no longer in existence.

@chiraggmodi
Copy link

chiraggmodi commented Apr 20, 2018

i am also facing same issue when i try to add foreach of post below is the code snipet

var el = wp.element.createElement,
    registerBlockType = wp.blocks.registerBlockType,
    withAPIData = wp.components.withAPIData;


registerBlockType( 'my-plugin/latest-post', {
    title: 'Latest Post',
    icon: 'megaphone',
    category: 'widgets',

    edit: withAPIData( function() {
        return {
            posts: '/wp/v2/posts?per_page=3'
        };
    } )( function( props ) {
        if ( ! props.posts.data ) {
            return "loading !";
        }
        if ( props.posts.data.length === 0 ) {
            return "No posts";
        }
        var className = props.className;
        var posts = props.posts.data;

        // posts.forEach(post => {
        //     console.log(post)
        // })
            
        
        posts.forEach(function(element) {
            console.log(element)
            var post =element;
            return el(
                'a', 
                { className: className, href: post.link },
                post.title.rendered
            );
        });
    } ),

    save: function() {
        // Rendering in PHP
        return null;
    },
 } );

@gziolo
Copy link
Member

gziolo commented Apr 23, 2018

@chiraggmodi - I think you are experiencing another issue with race conditions for withAPIData implementation which should be fixed with #6303.

@chiraggmodi
Copy link

@gziolo i am still not able to solve this isuse. Can you share a javascript snippet?

@gziolo
Copy link
Member

gziolo commented Apr 24, 2018

@chiraggmodi, I'm afraid, there is nothing to share. You can try with the branch opened together with #6303 or apply this diff locally: https://patch-diff.githubusercontent.com/raw/WordPress/gutenberg/pull/6303.diff.

@chiraggmodi
Copy link

chiraggmodi commented Apr 25, 2018

@gziolo i have change according to above PR, but same issue no changes.

@jasonbahl
Copy link

jasonbahl commented May 9, 2018

fwiw, this is kind of working for me right now. I still get console errors, but it does appear that my blocks are properly whitelisted.

const { unregisterBlockType, getBlockTypes } = wp.blocks;
const allowedBlocks = [
  'core/paragraph',
  'oshpd/cta-button',
  'oshpd/card-grid',
  'oshpd/latest-news',
  'oshpd/hero',
  'oshpd/homepage-hero',
  'oshpd/leadership-cards'
];

setTimeout ( () => {

  if ( 
    typeof unregisterBlockType !== 'undefined' && 
    getBlockTypes !== 'undefined' ) 
  {
    getBlockTypes().forEach( block => {
      if ( allowedBlocks.indexOf( block.name ) === -1 ) {
        unregisterBlockType( block.name )
      }
    } );
  }

}, 500 );

Console error

This is the error I see with the code above added. But it does seem that the blocks I have whitelisted are indeed whitelisted and no other blocks can be inserted, not even from the / slash command, nor from transform controls (which I know were also issues related to white/blacklisting/filtering allowed_blocks)

screen shot 2018-05-09 at 1 16 24 pm

@jasonbahl
Copy link

ugh. . .the setTimeout seems to also only partially solve the issue. Sometimes my blocks are whitelisted and sometimes they are not. Seems like this is a case of my code not being executed at the proper time. . .is there a more proper way to do what I'm trying here, like an action/filter that I can hook the whitelist to?

See the GIF below showing that the whitelist is sometimes applied, but on refresh it's sometimes not applied too. First 2 page loads show just the whitelisted blocks. 3rd one shows all 60+ blocks.

whitelist-inconsistent

@aduth
Copy link
Member

aduth commented May 10, 2018

DOMContentReady strikes again.

Seems like there's about a half dozen layers of callbacks nowadays which occur before blocks are actually registered.

This should work if your script also includes wp-edit-post as a dependency:

window._wpLoadGutenbergEditor.then( function() {
    console.log( wp.blocks.getBlockTypes() );
} );

This is a private function which probably shouldn't be relied upon.

Personally, I think the blocks should be registered immediately, as they were in earlier versions of hte plugin. The editor initialization should only be marking specific blocks as active.

@gziolo
Copy link
Member

gziolo commented May 11, 2018

Personally, I think the blocks should be registered immediately, as they were in earlier versions of hte plugin. The editor initialization should only be marking specific blocks as active.

That's an interesting idea. Now, I think a bit more about it. We could also apply all filters at the time those blocks would be marked as active. I think the only reason why it works as it works, it existed to give a chance plugins to modify core blocks properly. It seems like we can achieve the same by doing iteration over all registered blocks and applying filters to them just before the editor gets initialized.

@youknowriad
Copy link
Contributor

Personally, I think the blocks should be registered immediately, as they were in earlier versions of hte plugin. The editor initialization should only be marking specific blocks as active.

The PR exploring the blocks in store #6679 would allow us to have fine-tuning around parsing blocks only when their corresponding block get registered. So I was thinking a workflow like this is possible:

1- At Editor initialization, parse the blocks using the grammar only which will give us a list of block names and attributes.

2- A component is rendered for each one of these raw blocks. This component would be reactive to block registration: If the block type corresponding to the block name is registered, complete the parsing of the block (attributes) and render the block like we do currently. (making the block active)

3- If a registered block with the given name is not registered, mark the block as inactive which will show a prompt allowing you to edit it with classic block or html block unless some milliseconds after first rendering the block is registered which will trigger a rerender using the option 2. (Maybe we can have a delay or an event triggering the prompt to use classic block)

--
Anyway that's just an idea on how reactive parsing could work.

@danielbachhuber danielbachhuber added the [Status] Needs More Info Follow-up required in order to be actionable. label Oct 30, 2018
@danielbachhuber
Copy link
Member

@youknowriad @gziolo @aduth Is this issue still relevant or can it be closed?

@aduth
Copy link
Member

aduth commented Oct 30, 2018

As far as I know, the original issue still holds true, with the needed workaround being a "solution".

I think a better approach here would be to ensure the blocks are registered immediately, and change the parsing behavior to be more reactive, where an initial pass at content reveals only its raw data, and if/as blocks become registered, their renderings in the editor update accordingly. This would avoid issues we have today where all blocks need to be registered before the editor performs its parse, and would allow plugin authors to reference blocks at any time (after their direct registration from @wordpress/block-library).

If agreeable, we should consider closing this issue in favor of a new one which is more directed at the actionable task.

@gziolo
Copy link
Member

gziolo commented Oct 30, 2018

Just noting that I started refactoring which would allow to achieve what @aduth described in his last comment. See #10554. Let's discuss there would be the ideal flow which would satisfy all possible use cases we can imagine when handling registered blocks. I'm closing this one as won't fix as we don't want to invest more time into this issue as it is a consequence of the limitation of the blocks registry existing as of today.

@gziolo gziolo closed this as completed Oct 30, 2018
@gziolo gziolo added [Status] Not Implemented Issue/PR we will (likely) not implement. and removed [Status] Needs More Info Follow-up required in order to be actionable. labels Oct 30, 2018
@mcshaman
Copy link

Probably worth removing or amending the documentation on blacklisting or whitelisting blocks https://wordpress.org/gutenberg/handbook/extensibility/extending-blocks/#removing-blocks until this is resolved. I just spent hours trying to work out what I was doing wrong.

@gziolo
Copy link
Member

gziolo commented Nov 26, 2018

@mcshaman, there is #11723 opened where it is discussed how to solve it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Blocks Overall functionality of blocks [Feature] Extensibility The ability to extend blocks or the editing experience [Status] Not Implemented Issue/PR we will (likely) not implement. [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants