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

Save all attributes w/o source in markup (including ones that match default values) #22023

Closed
mevepe opened this issue May 1, 2020 · 2 comments
Labels
[Type] Help Request Help with setup, implementation, or "How do I?" questions.

Comments

@mevepe
Copy link

mevepe commented May 1, 2020

Hi, I'm trying to make a headless website with the Gutenberg editor.
For now, I'm facing a problem with passing block data as JSON response through REST API endpoint, because, as I mentioned, on save method, not all attributes are saved to block markup.

I'll try to describe the steps that I've made to achieve my plan:

  1. Extended base REST API for receiving page data:
/**
 * Include all Gutenberg blocks from content in REST API response
 *
 * 
 */
function gutenberg_blocks_to_rest_api($response, $post, $request)
{
    if (!function_exists('parse_blocks')) {
        return $response;
    }
    if (isset($post)) {
        $response->data['blocks'] = parse_blocks($post->post_content); // https://developer.wordpress.org/reference/functions/parse_blocks
    }
    return $response;
}
add_filter('rest_prepare_post', 'gutenberg_blocks_to_rest_api', 10, 3);
add_filter('rest_prepare_page', 'gutenberg_blocks_to_rest_api', 10, 3);
  1. Created my custom Gutenberg block with these attributes:
{
	"name": "cli/pure",
	"category": "basic",
	"attributes": {
		"value": {
			"type": "string",
			"default": "100%"
		},
		"prefix": {
			"type": "string",
			"default": "pure"
		},
		"tagName": {
			"type": "string",
			"default": "div"
		},
		"data": {
			"type": "string"
		}
	}
}

and following save method:

export default function save({ attributes, className }) {
	const {
		tagName: Tag,
		value,
		prefix,
	} = attributes;

	let expansion = false;

	const innerWrapClasses = classnames(`${prefix}__wrap`, {
	});

	const valueClasses = classnames(`${prefix}__value`, {

	});

	return (
		<Tag className={className} break-me="false">
			<div className={innerWrapClasses}>
				<h4 className={valueClasses}>{value}</h4>
			</div>
		</Tag>
	);
}
  1. And here's how I'm fetching blocks for the page:
export function Stories({ request, ...rest }) {
    const [hasError, setErrors] = useState(false);
    const [stories, setStories] = useState({});

    async function fetchData() {
        const res = await fetch(request);
        res
            .json()
            .then(res => setStories(res && res.blocks))
            .catch(err => setErrors(err));
    }

    useEffect(() => { fetchData() });

    return (
        <>
            {/* Render... */}
        </>
    );
};

On the screenshot below, I've snipped results of request:

As you can see, just one attribute of four loaded (and if it's value will be the same as default, zero attributes will load).

Effect that I'm trying to achieve here - using almost the same code on the edit/save function and on the frontend with full react support bypassing all attributes to request.

Any idea how I can achieve this?

@talldan talldan added the [Type] Help Request Help with setup, implementation, or "How do I?" questions. label May 4, 2020
@talldan
Copy link
Contributor

talldan commented May 4, 2020

@mevepe That default values aren't serialized with block data is by design.

For static blocks, the default is assigned when parsing the block data client side:

if ( value === undefined ) {
return attributeSchema.default;
}

Unfortunately, currently there's no server-side (PHP) capability for applying these defaults. That's tracked in #2751, so you wouldn't be able to apply the defaults in your gutenberg_blocks_to_rest_api function, unless you did this using your own implementation.

I'm not sure what your best option would be here, the crux seems to be that your application has a different flow to the post editor, which stores block data as HTML and parses that data client side, while your application parses server side and is then exposed to the problems outlined in #2751.

@youknowriad
Copy link
Contributor

Closing per the previous reply

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Help Request Help with setup, implementation, or "How do I?" questions.
Projects
None yet
Development

No branches or pull requests

3 participants