我有一个WP块<ServerSideRender />
后端中的组件。它可以很好地处理属性。但它不会返回$content
在前端的php回调中使用。
<ServerSideRender
block="mydomain/my-block"
attributes={ attributes }
/>
我在文档中找不到在使用$内容时是否有方法在后端动态呈现块。这个$content
是嵌套块,因此save()
使用方式如下:
save() {
return <InnerBlocks.Content />;
},
有人知道如何共犯吗?--编辑--我已添加当前edit()
密码请注意,并非所有内容都相关。重点在于:
使用InnerBlocks
ServerSideRender
/**
* WordPress dependencies
*/
const { __ } = wp.i18n;
const {
InnerBlocks,
InspectorControls,
MediaUpload,
MediaUploadCheck,
BlockControls,
} = wp.blockEditor || wp.editor; // Fallback to \'wp.editor\' for backwards compatibility
const {
PanelBody,
RangeControl,
Button,
SelectControl,
ToolbarGroup,
ToolbarButton,
ServerSideRender,
} = wp.components;
const { Component, Fragment } = wp.element;
const { withSelect, select } = wp.data;
const { compose } = wp.compose;
class BlockImageOverlayEdit extends Component {
render() {
const {
clientId,
attributes,
className,
setAttributes,
hasChildBlocks,
} = this.props;
const {
id,
preview,
editorSize,
bgColor,
mediaId,
mediaUrl,
centerContent,
mediaSpanCols,
mediaSpanOffset,
overlaySpanCols,
overlaySpanOffset,
alignX,
alignY,
} = attributes;
if ( id !== clientId ) {
setAttributes( { id: clientId } );
}
const colMaxAmount = 12;
const sizes = [ \'xs\', \'sm\', \'md\', \'lg\', \'xl\', \'xxl\' ];
const removeMedia = () => {
this.props.setAttributes( {
mediaId: 0,
mediaUrl: \'\',
} );
};
const onSelectMedia = ( media ) => {
setAttributes( {
mediaId: media.id,
mediaUrl: media.url,
} );
};
const onChangeColumns = ( value ) => {
const newMediaSpanOffset = (value + mediaSpanOffset) > colMaxAmount ? colMaxAmount - value : mediaSpanOffset;
setAttributes(
{
mediaSpanCols: value,
mediaSpanOffset: newMediaSpanOffset,
} );
};
const onChangeColumnsOverlay = ( value ) => {
const newOverlaySpanOffset = (value + overlaySpanOffset) > colMaxAmount ? colMaxAmount - value : overlaySpanOffset;
setAttributes(
{
overlaySpanCols: value,
overlaySpanOffset: newOverlaySpanOffset,
} );
};
const MyServerSideRender = () => {
// thought. maybe I can fetch, and prerender the inner blocks here, serialize them and set them as an attribute. Right before this return. (and at save() set it back to null)
return (
<ServerSideRender
block="mydomain/block-wp-block-image-overlay-01"
attributes={ attributes }
/>
);
};
const PreviewButton = () => (
<BlockControls>
<ToolbarGroup>
<ToolbarButton
icon={ preview ? \'hidden\' : \'visibility\' }
label="Preview"
onClick={ () => setAttributes( { preview: ! preview } ) }
/>
</ToolbarGroup>
</BlockControls>
);
const BreakpointButtons = () => (
<ToolbarGroup>
{ sizes.map( ( size, index ) => {
return (
<ToolbarButton
key={ index }
style={ { padding: 0.5 + \'em\' } } //TODO: fix spacing
isPrimary={ editorSize === size }
isSecondary={ editorSize !== size }
// icon={ edit }
label="Edit"
onClick={ () => setAttributes( { editorSize: size } ) }
>{ size }</ToolbarButton>
);
} ) }
</ToolbarGroup>
);
const AlignPanel = () => (
<PanelBody
title={ __( \'Column size\', \'mydomain\' ) }
initialOpen={ false }
>
<SelectControl
label={ __( \'Horizontal align\', \'mydomain\' ) }
value={ alignX }
options={ [
{ value: \'start\', label: __( \'Image on the right\', \'mydomain\' ) },
{ value: \'end\', label: __( \'Image on the left\', \'mydomain\' ) },
] }
onChange={ ( value ) => setAttributes( { alignX: value } ) }
/>
<SelectControl
label={ __( \'Vertical align\', \'mydomain\' ) }
value={ alignY }
options={ [
{ value: \'start\', label: __( \'Image on the top\', \'mydomain\' ) },
{ value: \'end\', label: __( \'Image on the bottom\', \'mydomain\' ) },
] }
onChange={ ( value ) => setAttributes( { alignY: value } ) }
/>
</PanelBody>
);
const ColumnPanel = () => (
<PanelBody
title={ __( \'Column size\', \'mydomain\' ) }
initialOpen={ false }
>
<BreakpointButtons/>
<RangeControl
label={ __( \'Image columns\', \'mydomain\' ) }
value={ mediaSpanCols }
onChange={ onChangeColumns }
min={ 1 }
max={ colMaxAmount }
/>
<RangeControl
label={ __( \'Overlay columns\', \'mydomain\' ) }
value={ overlaySpanCols }
onChange={ onChangeColumnsOverlay }
min={ 1 }
max={ colMaxAmount }
/>
</PanelBody>
);
const Media = () => (
<Fragment>
<MediaUploadCheck>
<MediaUpload
onSelect={ onSelectMedia }
value={ mediaId }
allowedTypes={ [ \'image\' ] }
render={ ( { open } ) => (
<Button
className={ mediaId === 0 ? \'editor-post-featured-image__toggle\' : \'editor-post-featured-image__preview\' }
onClick={ open }
>
{ mediaId === 0 && __( \'Choose an image\', \'mydomain\' ) }
{ mediaUrl !== undefined &&
<img alt={ \'\' } src={ mediaUrl }/>
}
</Button>
) }
/>
</MediaUploadCheck>
{
mediaId !== 0 &&
<MediaUploadCheck>
<MediaUpload
title={ __( \'Replace image\', \'mydomain\' ) }
value={ mediaId }
onSelect={ onSelectMedia }
allowedTypes={ [ \'image\' ] }
render={ ( { open } ) => (
<Button
onClick={ open }
isDefault
isLarge>{ __( \'Replace image\', \'mydomain\' ) }
</Button>
) }
/>
</MediaUploadCheck>
}
{
mediaId !== 0 &&
<MediaUploadCheck>
<Button
onClick={ removeMedia }
isLink
isDestructive>{ __( \'Remove image\', \'mydomain\' ) }
</Button>
</MediaUploadCheck>
}
</Fragment>
);
const Overlay = () => (
<InnerBlocks
templateLock={ false }
renderAppender={
hasChildBlocks ?
undefined :
() => <InnerBlocks.ButtonBlockAppender/>
}
/>
)
return (
<Fragment>
<InspectorControls>
<AlignPanel/>
<ColumnPanel/>
</InspectorControls>
<PreviewButton/>
{ ! preview &&
<div className={ `${ className }` } style={ { display: \'flex\' } }>
<div style={ { width: 50 + \'%\' } }>
<Media />
</div>
<div style={ { width: 50 + \'%\' } }>
<Overlay />
</div>
</div> }
{ preview &&
<MyServerSideRender /> }
</Fragment>
);
}
}
export default compose(
withSelect
( (
select
,
ownProps
) => {
const {
clientId
}
= ownProps;
const { getBlockOrder } =
select( \'core/block-editor\' ) || select( \'core/editor\' ); // Fallback to \'core/editor\' for backwards compatibility
return {
hasChildBlocks: getBlockOrder( clientId ).length > 0,
};
} )
)
( BlockImageOverlayEdit );