如何在Gutenberg富文本编辑器实现类链接弹窗的可编辑脚注按钮
Let's work through this issue together. The main gap in your current code is that it only toggles the format with a static data-note value, but doesn't include the modal interface needed to edit that attribute dynamically—just like how the default link button works. Here's how to modify your code to add that functionality:
Step 1: Import Required WordPress Components
First, we need to bring in additional components to handle modals, input fields, and state management:
import { Fragment, useState } from '@wordpress/element'; import { RichTextToolbarButton, RichTextShortcut } from '@wordpress/block-editor'; import { toggleFormat, registerFormatType, getActiveFormat } from '@wordpress/rich-text'; import { Modal, TextControl, Button } from '@wordpress/components';
Step 2: Update the Edit Function with Modal Logic
We'll add state to manage the modal's visibility and the current footnote text. When the toolbar button is clicked:
- If the format is already active, we'll pull the existing
data-notevalue and open the modal to edit it. - If it's not active, we'll open an empty modal to let the user input a new footnote.
Here's the revised footnote object:
const name = `custom/eos-footnote`; export const footnote = { name, title: 'Footnote', tagName: 'span', className: 'eos-footnote', attributes: { 'data-note': 'data-note', // Map the attribute correctly for rich text handling }, edit( { isActive, value, onChange } ) { const [ isModalOpen, setIsModalOpen ] = useState( false ); const [ currentNote, setCurrentNote ] = useState( '' ); // Fetch the active format to get existing footnote text const activeFormat = getActiveFormat( value, name ); const handleOpenModal = () => { // Pre-fill input if editing an existing footnote if ( activeFormat ) { setCurrentNote( activeFormat.attributes[ 'data-note' ] || '' ); } else { setCurrentNote( '' ); } setIsModalOpen( true ); }; const handleSaveNote = () => { let updatedValue; if ( activeFormat ) { // Update existing format with new note updatedValue = toggleFormat( value, { type: name, attributes: { 'data-note': currentNote, }, } ); } else { // Apply new format with the entered note updatedValue = toggleFormat( value, { type: name, attributes: { 'data-note': currentNote, }, } ); } onChange( updatedValue ); setIsModalOpen( false ); }; const handleCancel = () => { setIsModalOpen( false ); setCurrentNote( '' ); }; return ( <Fragment> <RichTextShortcut type="primary" character="n" onUse={ handleOpenModal } /> <RichTextToolbarButton icon="admin-post" title={ 'Footnote' } onClick={ handleOpenModal } isActive={ isActive } shortcutType="primary" shortcutCharacter="n" /> {/* Footnote Edit Modal */} { isModalOpen && ( <Modal title={ activeFormat ? 'Edit Footnote' : 'Add Footnote' } onRequestClose={ handleCancel } className="eos-footnote-modal" > <TextControl label="Footnote Text" value={ currentNote } onChange={ setCurrentNote } placeholder="Type your footnote here" autoFocus /> <div style={ { marginTop: '16px', display: 'flex', gap: '8px', justifyContent: 'flex-end' } }> <Button variant="secondary" onClick={ handleCancel }> Cancel </Button> <Button variant="primary" onClick={ handleSaveNote } disabled={ !currentNote.trim() }> { activeFormat ? 'Update' : 'Add' } </Button> </div> </Modal> ) } </Fragment> ); }, };
Step 3: Keep the Format Registration Function
Your existing registration code works perfectly, so we'll retain it:
function registerFormats () { [ footnote, ].forEach( ( { name, ...settings } ) => registerFormatType( name, settings ) ); }; registerFormats();
Key Improvements Explained:
- State Management: We use
useStateto track the modal's open/closed state and the current footnote text. - Active Format Detection:
getActiveFormatfetches the existing footnote format (if any) to pre-fill the input with saved text. - Modal Interface: The
Modalcomponent from@wordpress/componentscreates the popup, with aTextControlfor editing and buttons to save/cancel. - Dynamic Format Handling: When saving, we either update an existing footnote or apply a new one based on whether the format was already active.
This implementation will behave exactly like the default link button: clicking the toolbar button (or using Cmd/Ctrl + N) opens a modal to enter or edit footnote text, which is then stored in the data-note attribute of the <span class="eos-footnote"> element.
内容的提问来源于stack exchange,提问作者Rodolfo Estima Rodrigues

