英文:
WordPress Custom Widget Save Multiple Attributes?
问题
I am using the @wordpress/create-block package to build a simple widget. I do not understand how to make the save.js save more than one attribute.
我正在使用 @wordpress/create-block 包来构建一个简单的小部件。我不明白如何在 save.js 中保存多个属性。
I have 2 attributes defined in the block.json: theNotes and theContact.
我在 block.json 中定义了2个属性:theNotes 和 theContact。
"attributes": {
"theNotes": {
"type": "string",
"source": "text",
"selector": "div",
"default": ""
},
"theContact": {
"type": "string",
"source": "text",
"selector": "div",
"default": ""
}
}
My edit.js looks like this:
我的 edit.js 如下所示:
export default function Edit( { attributes, setAttributes } ) {
return (
<div { ...useBlockProps() }>
<div>
<TextControl
label={ __( 'The Notes', 'editor-notes' ) }
value={ attributes.theNotes }
onChange={ ( val ) => setAttributes( { theNotes: val } ) }
/>
</div>
<div>
<TextControl
label={ __( 'The Contact', 'editor-notes' ) }
value={ attributes.theContact }
onChange={ ( val ) => setAttributes( { theContact: val } ) }
/>
</div>
</div>
);
}
For the save.js file, I cannot find instructions on how to save both of those attributes using this default scaffolding. I thought something like this would work, but I get a block validation error. It says that both the attributes were saved twice to both attribute values.
对于 save.js 文件,我找不到有关如何使用默认脚手架保存这两个属性的说明。我认为像这样的代码会起作用,但我收到了一个块验证错误。错误显示两个属性都保存了两次到两个属性值。
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<div>{ attributes.theNotes }</div>
<div>{ attributes.theContact }</div>
</div>
);
}
The error says:
错误信息如下:
Content generated by `save` function:
<div class="wp-block-create-block-editor-notes"><div>notesTestcontactTest</div><div>notesTestcontactTest</div></div>
Content retrieved from post body:
<div class="wp-block-create-block-editor-notes"><div>notesTest</div><div>contactTest</div></div>
The Getting Started Guide shows how to save one attribute called "message" like this. Apparently, I do not know what to do when I have multiple attributes to update:
入门指南 展示了如何保存名为 "message" 的一个属性,如下所示。显然,我不知道如何处理多个要更新的属性:
import { useBlockProps } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return <div { ...blockProps }>{ attributes.message }</div>;
}
英文:
I am using the @wordpress/create-block package to build a simple widget. I do not understand how to make the save.js save more than one attribute.
I have 2 attributes defined in the block.json: theNotes and theContact.
"attributes": {
"theNotes": {
"type": "string",
"source": "text",
"selector": "div",
"default": ""
},
"theContact": {
"type": "string",
"source": "text",
"selector": "div",
"default": ""
}
}
My edit.js looks like this:
export default function Edit( { attributes, setAttributes } ) {
return (
<div { ...useBlockProps() }>
<div>
<TextControl
label={ __( 'The Notes', 'editor-notes' ) }
value={ attributes.theNotes }
onChange={ ( val ) => setAttributes( { theNotes: val } ) }
/>
</div>
<div>
<TextControl
label={ __( 'The Contact', 'editor-notes' ) }
value={ attributes.theContact }
onChange={ ( val ) => setAttributes( { theContact: val } ) }
/>
</div>
</div>
);}
For the save.js file, I cannot find instructions on how to save both of those attributes using this default scaffolding. I thought something like this would work, but I get a block validation error. It says that both the attributes were saved twice to both attribute values.
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<div>{ attributes.theNotes }</div>
<div>{ attributes.theContact }</div>
</div>
); }
The error says:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
Content generated by `save` function:
<div class="wp-block-create-block-editor-notes"><div>notesTestcontactTest</div><div>notesTestcontactTest</div></div>
Content retrieved from post body:
<div class="wp-block-create-block-editor-notes"><div>notesTest</div><div>contactTest</div></div>
<!-- end snippet -->
The Getting Started Guide shows how to save one attribute called "message" like this. Apparently, I do not know what to do when I have multiple attributes to update:
import { useBlockProps } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return <div { ...blockProps }>{ attributes.message }</div>;}
答案1
得分: 1
错误指示了save()
函数的问题;然而,这有点误导。block.json
中的属性选择器[1]
实际上是如何定义的,为"div"
,用于both theNotes
和 theContact
,导致了save
和post body
之间的内容不匹配。
由于定义的属性选择器不是唯一元素(在保存的内容中出现了3次<div>...</div>
),所以从帖子内容中提取数据的方法会匹配多次,因此两个属性都保存了<div>
和<div>
的文本内容。这导致错误消息中出现了"notesTestcontactTest"文本。
block.json(当前)
"attributes": {
"theNotes": {
"type": "string",
"source": "text", // the value saved for theNotes is the text
"selector": "div", // within this matching selector
"default": ""
},
"theContact": {
"type": "string",
"source": "text", // the value save for theContact is the text
"selector": "div", // with the same matching selector as theNotes
"default": ""
}
}
通过为两个属性的div
选择器添加唯一的类名,将使值正确保存和更新,例如:
block.json(已更新)
"attributes": {
"theNotes": {
"type": "string",
"source": "text",
"selector": "div.the-notes", // a div with the className "the-notes"
"default": ""
},
"theContact": {
"type": "string",
"source": "text",
"selector": "div.the-contact", // a div with the className "the-contact"
"default": ""
}
}
与使用TextControl
编辑块级元素的文本内容相比,RichText 组件更适合,例如<div>
:
edit.js
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function Edit( { attributes, setAttributes } ) {
return (
<div { ...useBlockProps() }>
<RichText
tagName="div" // Output as a <div>, no extra div needed
value={ attributes.theNotes }
onChange={ ( content ) => setAttributes( { theNotes: content } ) }
placeholder="Enter Notes.." // Optional
/>
<RichText
tagName="div" // Output as a <div>, no extra div needed
value={ attributes.theContact }
onChange={ ( content ) => setAttributes( { theContact: content } ) }
placeholder="Enter Contact.." // Optional
/>
</div>
)
}
然后,需要更新save()
函数,以确保属性选择器找到正确的匹配项以提取props.attributes
的值。可以在save
中使用RichText.Content
来渲染标签的标记和内容:
save.js
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<RichText.Content
tagName="div"
className="the-notes" // Used for the selector
value={ attributes.theNotes }
/>
<RichText.Content
tagName="div"
className="the-contact" // Used for the selector
value={ attributes.theContact }
/>
</div>
)
}
RichText
的tagName
也可以是另一个块级元素,如"h2"或"p",只要属性选择器匹配即可。在重新测试这些更改时,从编辑器中删除先前的块,保存,刷新/清除缓存,然后再次插入您的块。要确认属性正确保存,可以在编辑器中使用代码视图查看将要保存的标记,应该类似于:
<!-- wp:create-block/editor-notes -->
<div class="wp-block-create-block-editor-notes"><div class="the-notes">Notes Test</div><div class="the-contact">Contact Test</div></div>
<!-- /wp:create-block/editor-notes -->
英文:
The error indicates an issue with the save() function; however this is a little misleading. The content mismatch between save
and post body
is actually caused by how the attribute selector in block.json is defined as "div" for both theNotes
and theContact
.
Given the attributes selector defined is not a unique element (<div>...</div>
appears 3 times in the saved content), the method used to extract data from the post content gets multiple matches so both attributes save the text content of <div>
and <div>
again. This results in the "notesTestcontactTest" text seen in the error message.
block.json (current)
"attributes": {
"theNotes": {
"type": "string",
"source": "text", // the value saved for theNotes is the text
"selector": "div", // within this matching selector
"default": ""
},
"theContact": {
"type": "string",
"source": "text", // the value save for theContact is the text
"selector": "div", // with the same matching selector as theNotes
"default": ""
}
}
By adding a unique class name to div
selector of both attributes, the values will save and update correctly, eg:
block.json (updated)
"attributes": {
"theNotes": {
"type": "string",
"source": "text",
"selector": "div.the-notes", // a div with the className "the-notes"
"default": ""
},
"theContact": {
"type": "string",
"source": "text",
"selector": "div.the-contact", // a div with the className "the-contact"
"default": ""
}
}
The RichText component would be more suitable than using TextControl for editing content to be saved as text of block-level elements like <div>
, eg:
edit.js
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function Edit( { attributes, setAttributes } ) {
return (
<div { ...useBlockProps() }>
<RichText
tagName="div" // Output as a <div>, no extra div needed
value={ attributes.theNotes }
onChange={ ( content ) => setAttributes( { theNotes: content } ) }
placeholder="Enter Notes.." // Optional
/>
<RichText
tagName="div" // Output as a <div>, no extra div needed
value={ attributes.theContact }
onChange={ ( content ) => setAttributes( { theContact: content } ) }
placeholder="Enter Contact.." // Optional
/>
</div>
)
}
The save() function would then also need updating to ensure the attributes selector finds the right match to extract the props.attributes values. RichText.Content
can be used in save to render the tags markup and content:
save.js
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<RichText.Content
tagName="div"
className="the-notes" // Used for the selector
value={ attributes.theNotes }
/>
<RichText.Content
tagName="div"
className="the-contact" // Used for the selector
value={ attributes.theContact }
/>
</div>
)
}
The RichText
tagName could also be another block-level element like "h2" or "p" as long as the attributes selector matches. When retesting these changes to your block, remove the previous block from the Editor, save, refresh/clear the cache then insert your block again. To confirm the attributes save corrently, in the Editor use the Code view to see the markup that will be saved, it should be something like:
<!-- wp:create-block/editor-notes -->
<div class="wp-block-create-block-editor-notes"><div class="the-notes">Notes Test</div><div class="the-contact">Contact Test</div></div>
<!-- /wp:create-block/editor-notes -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论