Gutenberg: CPTs – saving data from core blocks to meta?

Created on 8 Nov 2018  Â·  7Comments  Â·  Source: WordPress/gutenberg

Really glad that we can create CPT templates containing custom blocks that will save data to post meta. https://wordpress.org/gutenberg/handbook/block-api/attributes/#meta

However! A lot of the time these fields are really basic (e.g. for a CPT ‘book’, think of text fields for author, genre, etc). It would seem overkill to create a custom block for each of these items – just so we can save the data to the right post meta field.

What would be the correct ‘Gutenberg’ way of doing this, given that porting custom fields to blocks is encouraged? Is there any way (without using ACF or similar) of creating lots of e.g. Paragraph blocks each saving to a different meta field?

The rational for doing this is to ensure we continue to save structured data, allowing us to pull specific items out and use them in places other than the single template file. Am I missing something here?

Also posted this here; sorry for the double post but I'm very concerned to understand the right 'Gutenberg' way of handling what must be a very common scenario for agencies.

[Type] Help Request

Most helpful comment

@hexagongirl Sure, sorry! I should've done that instantly. It was just a spontaneous reaction upon seeing that.

It's an interesting idea for sure, but in my opinion not something that's feasible for all the existing blocks out there.

core/paragraph is so much more than just plain text. Each block itself has attributes (e.g. font size, color, etc.) that would need to be stored as well. At this point that's too much information that it's truly useful for the use case (displaying the book's author). This way you couldn't even sort books by their author because you don't have the information in plain text.

Then there are lots of dynamic blocks and blocks which itself store data as post meta. How would these be handled when you define storage in the template as well? There'd be no easy way to get all the data straight away.

Circling back to your original question:

What would be the correct ‘Gutenberg’ way of doing this, given that porting custom fields to blocks is encouraged? Is there any way (without using ACF or similar) of creating lots of e.g. Paragraph blocks each saving to a different meta field?

You could totally create a single block containing multiple input fields that all save to post meta.

I'm taking a recent plugin of mine as an example.

In it, I define a template for my post type to only allow my custom block type.

Then I register this specific block type that has two input fields, both saving to post meta.

If you want to to use some of these input fields in other places, you could also register separate blocks for them. You don't even have to repeat all the config options (supports, edit, etc. you could extract these to separate variables and loop over them. You'd end up with something like this:

const blockTypes = [
  {
    name: '...',
    // ...
  },
  {
    name: '...',
    // ...
  }
]

for (let blockType of blockTypes) {
  registerBlockType(blockType.name, ...);
}

All 7 comments

There is a plugin called _Gutenberg Custom Fields_. I think this is what you are looking for:
https://youknowriad.github.io/gcf

Thanks @Soean - appreciate the pointer. I did see/try GCF earlier this week, but wasn't sure whether it was a long-term project (https://wordpress.org/support/topic/plan-for-the-plugin/).

How feasible would it specify in a Gutenberg template that a core block should save to meta? Do you know if this idea has been suggested/considered already?

Imagine adding a third parameter to the 'template' arg of register_post_type:

    $args = array(
        'public' => true,
        'label'  => 'Books',
        'show_in_rest' => true,
        'template' => array(
            array( 
                'core/paragraph',
                array(),
                array(
                    'source' => 'meta',
                    'meta' => 'my_author_custom_field'
                )
            )
        )
    );
    register_post_type( 'book', $args );

@swissspidy thanks for the thumbs down; would you be able to explain the rational behind it - was it the idea? the code (which I know was 'pie in the sky')? the wrong place to raise this issue?

If I don't know, I can't learn...

@hexagongirl Sure, sorry! I should've done that instantly. It was just a spontaneous reaction upon seeing that.

It's an interesting idea for sure, but in my opinion not something that's feasible for all the existing blocks out there.

core/paragraph is so much more than just plain text. Each block itself has attributes (e.g. font size, color, etc.) that would need to be stored as well. At this point that's too much information that it's truly useful for the use case (displaying the book's author). This way you couldn't even sort books by their author because you don't have the information in plain text.

Then there are lots of dynamic blocks and blocks which itself store data as post meta. How would these be handled when you define storage in the template as well? There'd be no easy way to get all the data straight away.

Circling back to your original question:

What would be the correct ‘Gutenberg’ way of doing this, given that porting custom fields to blocks is encouraged? Is there any way (without using ACF or similar) of creating lots of e.g. Paragraph blocks each saving to a different meta field?

You could totally create a single block containing multiple input fields that all save to post meta.

I'm taking a recent plugin of mine as an example.

In it, I define a template for my post type to only allow my custom block type.

Then I register this specific block type that has two input fields, both saving to post meta.

If you want to to use some of these input fields in other places, you could also register separate blocks for them. You don't even have to repeat all the config options (supports, edit, etc. you could extract these to separate variables and loop over them. You'd end up with something like this:

const blockTypes = [
  {
    name: '...',
    // ...
  },
  {
    name: '...',
    // ...
  }
]

for (let blockType of blockTypes) {
  registerBlockType(blockType.name, ...);
}

Thanks @swissspidy, I do appreciate that, and glad I understand better now why this wouldn't work in practice (would still be brilliant if it existed, but we have to be pragmatic at this stage!!)

It's really useful to see your implementation of a multi-field block. I'd discounted this approach as contrary to the whole 'drag and drop' ethos of Gutenberg, but putting my pragmatic hat on again, I can see it would work well for structured data.

And yes, I guess there'd be no reason why for simple text fields, we couldn't just loop over several and apply the same logic to each. Will give it a go!

As for multi-field blocks it obviously depends on the use case, i.e. whether it's a block meant only for a specific post type, whether it can be used multiple times or not, and whether there's a (locked) template.

Sure - as with a lot of things, it'll be about choosing the most effective approach on a project-by-project basis I guess.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

spocke picture spocke  Â·  3Comments

youknowriad picture youknowriad  Â·  3Comments

davidsword picture davidsword  Â·  3Comments

nylen picture nylen  Â·  3Comments

JohnPixle picture JohnPixle  Â·  3Comments