-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Dynamic blocks: default values for attributes aren't converted into html comments #7342
Comments
Slight push on this one. Is this intended? |
Hi @katerlouis, What you've documented is the current behavior, yes. I've flagged this for review; we may consider changing the behavior in the future. |
@danielbachhuber Is there a trick / workaround which forces gutenberg to write the value in the comment? |
@katerlouis Not to my knowledge, no. |
With moving block definitions to the server, I expect the preparation of generating attributes for That default values are not encoded in comments is the expected behavior. gutenberg/blocks/api/serializer.js Lines 154 to 157 in 7a878e0
See also #1905 |
I'm inclined to close this under the umbrella of #2751, as it essentially becomes a non-issue once implemented. For near-term, as a plugin developer you're best off to register your block attributes on the server. They should be inherited into the client automatically. If there's an issue with this, it can be addressed separately. Otherwise, it's expected that the server is respecting gutenberg/lib/class-wp-block-type.php Lines 144 to 146 in 7a878e0
|
Although closed, I would like to add to this topic. An attribute's The Block API Handbook shows that this attribute can be given a I'm not sure if this issue affects a standard block type (because the align attribute will be rendered as actual HTML), but the issue becomes apparent when working with a dynamic block type. A dynamic block relies on all the attributes to be available to its Upon further reading, it seems that the "solution" is to define the The issue with this "solution" is that all dynamic blocks are vulnerable to having their "align" setting bulk updated if the developer decides to change this This could cause a lot of headaches to web developers. |
If there was no explicit user interaction, I'd see this as working as intended in treating it as an undefined value which should defer to the block's default, even if that default changes over time. Could this be confusing for a user in that their content could suddenly appear different? Perhaps, but the use-case for a block changing its default seem uncommon such that in the event it was to occur, I think it'd be more confusing to the user that the new default not take effect for a block in which they had made no choice to its value. Now, if the user had taken an explicit action in choosing a value which happened to align with the block's current default at the time, I'd probably agree that this should be included in the comment demarcation, such that the choice be respected should the default be updated in the future. None of this speaks to the availability of the value on the server, which I still hold is better accounted for by #2751. |
Hi @aduth Thanks for the reply and input. I still believe this is something that should be improved but is ultimately your decision. Here is a workaround I have implemented to allow a "default value" to be defined whilst allowing the block to include this attribute value to be serialized: /**
* withDataAlign
*
* Fixes a bug where block attribute "default values" are not saved in serialized data.
* Extend the default BlockListBlock component and apply a default "align" value allowing
* Gutenberg to serialize the "align" setting (normally ignored).
*
* @see https://github.com/WordPress/gutenberg/issues/7342#issuecomment-435371583
* @date 5/11/18
* @since 5.8.0
*
* @param object BlockListBlock The BlockListBlock element.
* @return createElement
*/
var withDataAlign = wp.compose.createHigherOrderComponent(function( BlockListBlock ) {
return function( props ) {
// get blockType
var blockType = wp.blocks.getBlockType( props.block.name );
// add default
if( props.block.attributes.align === undefined && blockType.align ) {
props.block.attributes.align = blockType.align;
}
// return
return wp.element.createElement(
BlockListBlock,
props
);
};
}, 'withDataAlign' );
wp.hooks.addFilter( 'editor.BlockListBlock', 'acf/with-data-align', withDataAlign ); Hopefully this can help other developers experiencing the same problem or spark some more conversation. |
An issue you may encounter in this implementation is that you're mutating the attributes object directly, rather than going through the store's actions (e.g. |
@aduth Thanks for the tip. Is this similar to the |
Under the hood, they are effectively the same (with some small differences).
This is the sort of subtle issue I had in mind in my previous issue. I wonder if this may be the same issue which is set to be addressed in #11777, specifically affecting components which dispatch during their mount. |
Just ran into this issue. To add more confusion, I've noticed that for some attribute types (notably booleans) the attribute isn't even passed into the $my_attr = isset($attributes['myAttr']) ? $attributes['myAttr'] : $my_attr_default; This lead me to try defining the attributes in PHP via Unclear why these two seemingly equivalent APIs behave differently, but at this point I'm inclined to move as much of the block definition as I can to a shared format (json?) and pull data into either environment as needed. Please just somebody review the APIs and normalize them 🤦 this is hardly the first time I've bumped into issues where both of these APIs behave differently. |
This isn't a helpful way of engaging. A lot of people are working to solve this problem in a way that meets very different and almost conflicting requirements. That said:
That has been the direction for a long time, in incremental steps. Most recently: #22491. With that in, it should now be much more feasible for the back-end block renderer to consider default attribute values. |
Extending on what @mcsf shared, as of today in Gutenberg plugin, all blocks but Embed set of blocks are registered on the server with all defaults for attributes listed in their definitions (when provided). |
First and foremost, excuse the frustration expressed before—you're correct, not constructive. All the guidance (or most of it anyway) I've seen across the web seems to suggest that registering attributes first and foremost happens via the JavaScript API, not the PHP API. This is including the WordPress Block Tutorial and the examples codebase, which presumably would be the starting point for most developers venturing into creating custom blocks. Of course this is without mentioning countless blog posts and tutorials out there which WordPress doesn't have control over. If this has been the direction for a while, perhaps it hasn't been portrayed clearly enough? What's a good place to start steering people in the direction of the PHP API for attribute registration? Submit PRs to the Handbook docs? |
Question: Is the intent roughly to move in the direction of defining blocks via Lines 96 to 115 in b83f948
|
I would guess that information spreads unevenly depending on the source and the message, and so you'll find seemingly conflicting information despite efforts to communicate an intended direction. The first discussion, #2751, is almost three years old. Aiming to solve the question of server-side block awareness, it argued in favour of environment-agnostic ways to describe a block type, including its attribute schema. The most natural candidate was JSON, but at the time it wasn't yet clear whether the source should be a declaration in PHP which could generate JSON, or vice-versa. More recently, a long and more visible discussion on this was #13693. It referenced #2751 for context, saw a ton of discussion, and produced a Markdown document (now outdated) explaining where we were headed with JSON declarations. This was early last year. A still open follow-up issue is #16209. Meanwhile, block registration has been increasingly happening on the server in Core/Gutenberg. Recently, #22491 was the culmination of this. The idea is that we can all benefit from the server having knowledge of all block types, as opposed to just dynamic ones (an earlier approach). Also, since early on, the very useful (and official) block creation tool That said, client-side registration has never been compromised or discouraged (and in fact server-side registration ultimately triggers client-side registration) and was the first-ever API for block registration. That, combined with its overall simplicity, make it a great showcase for tutorials and the like (e.g. a single JS file can register a block and define its edit and save methods). Plus, as you point out, documentation can become out of sync with emerging priorities. It's not that the docs are now wrong, but they could use some refresh. Ultimately, all of these could be causes for the apparent predominance of the JS API for block registration. |
@emilio-martinez: you may want to keep an eye on #22151. |
Wouldn't this work? registerBlockType('blah', {
title: 'blah',
category: 'blah',
attributes: {
att1: { type: 'string', default: '' },
att2: { type: 'string', default: '' },
att3: { type: 'string', default: '' },
},
edit: ({ attributes, setAttributes, className }) => {
useEffect(() => {
const initialAttributes = {
att1: 'blah 1',
att2: 'blah 2',
att3: 'blah 3',
}
const defaultAttributes = {}
for (const a in attributes) defaultAttributes[a] = attributes[a] || initialAttributes[a]
setAttributes(defaultAttributes)
}, [])
//...
}) |
The default attributes values are not saved. See WordPress/gutenberg#7342
I stumbled on this problem today. I'm inclined to pass the registered attributes from PHP to JS using a preloaded REST API endpoint. I'm suggesting something like what's done here: gutenberg/lib/edit-site-page.php Lines 151 to 170 in 459ab7f
And add a REST API endpoint that retrieves the list of registered block attributes, as well. That could be merged in with the JavaScript's |
For a custom plugin, I am facing this issue, I am parsing blocks and using them as API, in that case, all default attributes are missing and there is no way to get values until the user touched or changes the value of the input for example: |
I'm experiencing this also trying to set a default backgroundColor value. Say I set the default in the block.json file:
In the editor, the appropriate class for the background color (i.e. "has-xyz-background-clor") gets applied, but it doesn't also get applied on the front end via get_block_wrapper_attributes. What's more, if I do manually choose a different background color than the default and publish, the editor and get_block_wrapper_attributes both apply it properly, but if I then manually re-select the background color I have set as the default in block.json, it no longer gets added via get_block_wrapper_attributes. As a result, not only am I unable to set a default background since it won't appear initially on the front-end, but also if I set a default background then that particular color is unable to be selected for the front end, manually or otherwise, though all other colors are selectable. |
This was happening because of this issue: WordPress/gutenberg#7342 Therefore, I had to use `useEffect` to set the default values of the attributes. Here is the list of changes I made: 1. Removed default values from `block.json` for `query`, `tagName`, and `displayLayout`. 2. Moved the default values to `constants.ts` and created a new object `DEFAULT_ATTRIBUTES` to store them. 3. Relocated `constants.ts` from `inspector-controls` to the parent directory. 4. Refactored `edit.tsx` to use `DEFAULT_ATTRIBUTES` from `constants.ts` to set default attributes using `useEffect`. 5. Removed the attributes assignment from `registerBlockType` in `index.tsx`. 6. Updated `columns-control.tsx`, `index.tsx`, `order-by-control.tsx`, and `stock-status-control.tsx` to import from the relocated `constants.ts`. 7. Updated `ProductCollectionAttributes` and `ProductCollectionQuery` in `types.ts` to include `tagName` and `isProductCollectionBlock` respectively. 8. Modified `ProductCollection.php` to match the updated `orderBy` key in the query parameter. This refactor enhances the readability of the code and reduces duplication by keeping all constants and default values in one place.
* Add columns control to product collection block editor settings - `InspectorControls` from './inspector-controls' is now imported in `edit.tsx` and used in the returned JSX of `Edit` function. - A new file `columns-control.tsx` is added under 'product-collection' block's 'inspector-controls' directory which exports a `ColumnsControl` component. This component uses `RangeControl` from '@wordpress/components' to control the number of columns in the product collection display layout when the layout type is 'flex'. - The types file (`types.ts`) for 'product-collection' block is updated. The `Attributes` interface is renamed to `ProductCollectionAttributes` and the `ProductCollectionContext` interface is removed. The `ProductCollectionAttributes` now includes 'queryContext', 'templateSlug', and 'displayLayout' properties. * Refactor: Simplify Fallback Return in ColumnsControl Component This commit simplifies the fallback return value of the ColumnsControl component. Instead of returning an empty fragment (<> </>), it now returns null when the condition isn't met. This change improves readability and aligns with best practices for conditional rendering in React. * Feature: Add 'Order By' Control to Product Collection Inspector This commit adds a new 'Order By' control to the product collection inspector. The control allows users to specify the order of products in a collection by various attributes such as title and date. To support this, a new component 'OrderByControl' has been created and included in the product collection inspector. Additionally, the types for 'order' and 'orderBy' attributes have been updated and exported for reuse. * Add more options to OrderBy type * Add orderby handling on frontend & editor The main changes include: 1. Added a new property 'isProductCollectionBlock' in the block.json to denote if a block is a product collection block. 2. In the ProductCollection PHP class, a new initialization function has been defined to hook into the WordPress lifecycle, register the block, and update the query based on this block. 3. Added methods to manage query parameters for both frontend rendering and the Editor. 4. Expanded allowed 'collection_params' for the REST API to include custom 'orderby' values. 5. Defined a function to build the query based on block attributes, filters, and global WP_Query. 6. Created utility functions to handle complex query operations such as merging queries, handling custom sort values, and merging arrays recursively. These improvements allow for more flexible and robust handling of product collections in both the front-end display and the WordPress editor. It also extends support for custom 'orderby' values in the REST API, which allows for more advanced sorting options in product collections. * Add 'on sale' filter and enhance settings management in product collection block This commit introduces several changes to the product collection block. - First, it adds a new 'on sale' filter that can be used to display only the products that are currently on sale. - It also refactors the settings management in the product collection block to use the experimental ToolsPanel component from WordPress, which provides a more flexible and intuitive way to manage block settings. - It moves the 'Columns' control into the ToolsPanel, along with the 'Order by' control. - A new utility function `setQueryAttribute` is introduced to simplify setting nested query parameters. - The structure of the `ProductCollectionAttributes` and `ProductCollectionQuery` types have been adjusted to accommodate the changes. - Finally, it makes corresponding changes in the PHP part to handle the new 'on sale' query parameter. This should enhance the flexibility and user-friendliness of the product collection block. * Add stock status filter to WooCommerce product collection block This commit introduces a stock status filter to the WooCommerce product collection block. The changes include: 1. Added the ability to filter products based on their stock status within the 'product-collection' block. A new stock status control is created within the inspector-controls of the block. 2. A new 'get_stock_status_query' function is introduced in 'ProductCollection.php' which returns a query for products depending on their stock status. Please note that the stock status filter will only appear in the experimental build for now. * Refactor Stock Status control of Product Collection block This commit refactors the Stock Status control. The changes aim to improve the code organization and make the behavior of the component more explicit. The key modifications are: 1. Moved stock status related constants and functions from `inspector-controls/utils.tsx` to `inspector-controls/constants.ts`. This is done to ensure that all constants and similar utility functions are organized in one place. 2. Updated `product-collection/index.tsx` to import `getDefaultStockStatuses` from `inspector-controls/constants` instead of `inspector-controls/utils`. 3. Updated `stock-status-control.tsx` to determine whether the stock status has value or not by comparing with the default stock statuses using `fastDeepEqual`. If the stock status control is deselected, it resets the stock status to the default statuses. These changes do not introduce any new functionalities, but improve the readability and maintainability of the code. * Fix: Default values of attributes not saving as serialized block comment This was happening because of this issue: WordPress/gutenberg#7342 Therefore, I had to use `useEffect` to set the default values of the attributes. Here is the list of changes I made: 1. Removed default values from `block.json` for `query`, `tagName`, and `displayLayout`. 2. Moved the default values to `constants.ts` and created a new object `DEFAULT_ATTRIBUTES` to store them. 3. Relocated `constants.ts` from `inspector-controls` to the parent directory. 4. Refactored `edit.tsx` to use `DEFAULT_ATTRIBUTES` from `constants.ts` to set default attributes using `useEffect`. 5. Removed the attributes assignment from `registerBlockType` in `index.tsx`. 6. Updated `columns-control.tsx`, `index.tsx`, `order-by-control.tsx`, and `stock-status-control.tsx` to import from the relocated `constants.ts`. 7. Updated `ProductCollectionAttributes` and `ProductCollectionQuery` in `types.ts` to include `tagName` and `isProductCollectionBlock` respectively. 8. Modified `ProductCollection.php` to match the updated `orderBy` key in the query parameter. This refactor enhances the readability of the code and reduces duplication by keeping all constants and default values in one place. * Replace usage of 'statii' with 'statuses' in stock status handling This commit replaces all instances of 'statii' with the correct term 'statuses' in the context of handling stock status. This change affects three files: 1. `assets/js/blocks/product-collection/inspector-controls/stock-status-control.tsx` - The term is corrected in a comment block. 2. `assets/js/blocks/product-collection/types.ts` - Updated the name of a variable in the `ProductCollectionQuery` interface. 3. `src/BlockTypes/ProductCollection.php` - Here, the term is replaced in several locations including variable names, comments and the method `get_stock_status_query`. This commit helps improve code readability and consistency across the repository.
@tcmulder Here is another plot in the issue. If you set default attribute like you did. This apply to all kind of attributes not only BGColour. |
I'm quite surprised that the current state is the default behavior. I'm definitely in support of immediately inserting the appropriate default value attributes in the HTML comment markup for freshly inserted blocks. The current state, where the UI and editor will show colors and the like that aren't yet present in the post_content feels wrong. |
This is an incredibly annoying bug that I am also experiencing. I have also found that once a default value has been added to an attribute, removing it does not revert the behaviour to what you would expect - the attribute is still not found within the block attributes/markup. |
For a totally different block than before, I was trying to set default values for the block upon insertion, and am once again disheartened by the fact that this doesn't seem possible. I strongly believe that the following should be possible: Developers can set default attributes for blocks that are used when inserting the block. These are immediately present in the meta, and the UI immediately shows their values. Doing so should make no changes to previously inserted blocks. For example, we recently decided that - in our theme - buttons should default to a background color of red (one of our brand's colors). We'd like any NEW buttons, inserted from here forward, to be inserted with red backgrounds (and the UI shows red selected). Of course, users can then change the colors to whatever they want. And we also want to make no changes to previously inserted blocks - only new ones going forward. I believe this kind of default should be possible, but it does not appear to be the case. |
Describe the bug
When an attribute isn't changed, the value will not be written into the serialized html comment, which in fact, makes it unaccessible for PHPs
render_callback
-function.To Reproduce
Steps to reproduce the behavior:
var_dump()
the$attribues
in'render_callback
5b. or look into database, the html comment doesn't contain 'number'
Expected behavior
To avoid syncing the defaults in both php and js, I expect gutenberg to save defaults into the html comment aswell.
Desktop (please complete the following information):
Additional context
The text was updated successfully, but these errors were encountered: