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

How to server render block with nested blocks? #6751

Closed
mejta opened this issue May 15, 2018 · 14 comments
Closed

How to server render block with nested blocks? #6751

mejta opened this issue May 15, 2018 · 14 comments
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Extensibility The ability to extend blocks or the editing experience Needs Technical Feedback Needs testing from a developer perspective. [Type] Help Request Help with setup, implementation, or "How do I?" questions.

Comments

@mejta
Copy link

mejta commented May 15, 2018

Hi,

I have a block that uses InnerBlocks that I want to have server-rendered:

const { __ } = wp.i18n;
const { Button } = wp.components;
const { MediaUpload, InnerBlocks } = wp.blocks;

export const attributes = {
  background: {
    type: 'string',
  },
  backgroundUrl: {
    type: 'string',
  },
};

export const edit = ({ attributes, setAttributes }) => (
  <section
    className="partners-main"
    style={{ background: `center / cover no-repeat url(${attributes.backgroundUrl})` }}
  >
    <MediaUpload
      onSelect={image => setAttributes({
        background: image.id,
        backgroundUrl: image.sizes['full'],
      })}
      type="image"
      value={attributes.backgroundId}
      render={({ open }) => (
        <Button className={'button button-large'} onClick={open}>
          { __( 'Upload the background' ) }
        </Button>
      )}
    />
    <InnerBlocks />
  </section>
);

export const save = () => null;

I'm trying to do a server-rendering:

<?php
namespace App;

$theme = explode('/', get_stylesheet(), 2)[0];

function render_block_partners_main($attributes, $content = null) {
    var_dump($attributes, $content); // returns array(1) { ["backgroundUrl"]=> string(73) "https://localhost:3000/wp-content/uploads/sites/2/2018/02/sp-partneri.png" } NULL
    return sage('blade')->render('blocks.partners-main', $attributes);
}

register_block_type($theme . '/partners-main', [
    'render_callback' => __NAMESPACE__ . '\\render_block_partners_main',
]);

I would imagine similar behaviour like with shortcodes where I get nested blocks in $content attribute. Is it something that is in the roadmap or something I can achieve now but don't know how?

Thank you.
Dan

@danielbachhuber danielbachhuber added [Feature] Extensibility The ability to extend blocks or the editing experience [Type] Help Request Help with setup, implementation, or "How do I?" questions. labels May 15, 2018
@danielbachhuber danielbachhuber added the [Feature] Block API API that allows to express the block paradigm. label Jun 18, 2018
@mtias mtias removed this from the Merge: Plugins milestone Oct 3, 2018
@manake
Copy link

manake commented Oct 31, 2018

Is there a possibility of introducing multiple InnerBlocks per block? Like this:

el( wp.editor.InnerBlocks, {
	value: someAttribute,
	onChange: function( content ) {
		props.setAttributes({ someAttribute: content });
	}
} ),

el( wp.editor.InnerBlocks, {
	value: someAttribute2,
	onChange: function( content ) {
		props.setAttributes({ someAttribute2: content });
	}
} ),

This would be more useful.

Currently it's only possible to achieve this using a workaround of creating a second block. This is almost acceptable.

If I could save InnerBlocks in an array (as I can with RichText) then it would be also an advantage.

@noel-schenk
Copy link

@antonia-rose
Copy link

Is there a Timetable for this? We currently have a custom block with core/freeform and Timber rendering and right now this breaks our custom block.

@chrisvanpatten
Copy link
Contributor

I’m going to dig into this today. As it turns out I need this for a client project myself, so I’ll report back what I find.

@rogerlos
Copy link

rogerlos commented Nov 28, 2018

I gave up on this and just accept that Innerblocks containers have to be rendered in JS, which is less than ideal, to say the least.

For my purposes, if the server-side render of an Innerblocks container was handed an array like:

[
    'my_container_title' => 'blah',
    'my_inspector_field' => 'bleh',
    'innerblocks' => [
        [
            'namespace' => 'core',
            'name' => 'paragraph',
            'attributes' => [ ... ],
            'render_callback' => null,
            'rendered' => '<p>...</p>'
        ],
        [
            'namespace' => 'superduper',
            'name' => 'amazingblock',
            'attributes' => [ ... ],
            'render_callback' => 'superduper_function' // callable of any sort
            'rendered' => '<div>...</div>'
        ],
        ...
    ]
]

That's "all" that's needed. (Edited to add that knowing if there is a server-side render function registered would allow me to call that instead of relying on the pre-rendered content; in that way, if I have multiple custom blocks which do server-side renders I could provide them with context information in PHP, since that's nearly impossible to achieve in JS, apparently.)

@chrisvanpatten
Copy link
Contributor

Hey sorry all for the delay but it is possible to have an InnerBlocks and render your block on the server. I have a sample plugin but have been offline today. I’ll push it up as soon as I can.

@designsimply designsimply added the Needs Technical Feedback Needs testing from a developer perspective. label Dec 21, 2018
@MetarDev
Copy link

MetarDev commented Jan 4, 2019

@chrisvanpatten Hi! Got any update on this?

@mejta
Copy link
Author

mejta commented Jan 4, 2019

Now it looks it works. Here are my examples:

Here is how my JS save function of the block looks like. Whatever you return in save function is in $content variable of PHP render function.

function save() {
  return <InnerBlocks.Content />;
}

and here is my render PHP function:

function render($attributes, $content) {
  return '<div>doing some server magic :) ' . uniqid() . '<br />' . $content . '</div>';
}

So I would consider it as solved!

@Tofandel
Copy link

Tofandel commented May 26, 2019

It doesn't work if the innerblocks is a dynamic block as well... But if it's not dynamic it works... That definitely sounds like a bug

@mcsf
Copy link
Contributor

mcsf commented Aug 22, 2019

It doesn't work if the innerblocks is a dynamic block as well... But if it's not dynamic it works... That definitely sounds like a bug

Hi. This appears to be unrelated to the current issue.

Feel free to open a new one, and if so please provide some context, such as intended use cases. Thanks.

@AvidRambo
Copy link

It doesn't work if the innerblocks is a dynamic block as well... But if it's not dynamic it works... That definitely sounds like a bug

Did you find a solution for this?

@niklasp
Copy link
Contributor

niklasp commented Nov 1, 2020

stil today I need a solution for the same problem

@Tofandel
Copy link

Tofandel commented Nov 2, 2020

Yes the issue was within my hooks, I really don't remember what was my issue and how I solved it but there is no issue there with gutenberg, I think maybe I just forgot to return the result in the dynamic block or I had a bad condition returning nothing

@hrrarya
Copy link

hrrarya commented Sep 27, 2021

guy's Any Solution? Has anyone been able to use the Parent Block $attributes to Child Block in the server?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Extensibility The ability to extend blocks or the editing experience Needs Technical Feedback Needs testing from a developer perspective. [Type] Help Request Help with setup, implementation, or "How do I?" questions.
Projects
None yet
Development

No branches or pull requests