The heading command system provides programmatic control over heading application and state management. Commands enable both UI components and external code to apply heading formats and query the current heading state.
Command for applying headings to selected blocks and tracking the current heading state.
/**
* Command for applying headings. Used by the heading feature to apply headings.
*/
class HeadingCommand extends Command {
/** Current heading level or false if not in heading */
declare public value: false | string;
/** Set of supported model element names */
readonly modelElements: Array<string>;
/**
* Creates a heading command instance.
* @param editor - Editor instance
* @param modelElements - Array of supported heading model element names
*/
constructor(editor: Editor, modelElements: Array<string>);
/**
* Updates command state based on selection.
* Called automatically when selection changes to update value and isEnabled properties.
*/
refresh(): void;
/**
* Applies heading to selected blocks.
* @param options - Command options
* @param options.value - Heading level to apply (e.g., 'heading1', 'paragraph')
*/
execute(options: { value: string }): void;
}Usage Examples:
// Get the heading command
const headingCommand = editor.commands.get('heading');
// Apply different heading levels
editor.execute('heading', { value: 'heading1' });
editor.execute('heading', { value: 'heading2' });
editor.execute('heading', { value: 'heading3' });
// Convert to paragraph
editor.execute('heading', { value: 'paragraph' });
// Check current state
console.log(headingCommand.value); // 'heading1', 'heading2', etc., or false
console.log(headingCommand.isEnabled); // boolean - whether command can be executed
// Listen for command state changes
headingCommand.on('change:value', (evt, propertyName, newValue, oldValue) => {
console.log(`Heading changed from ${oldValue} to ${newValue}`);
});
headingCommand.on('change:isEnabled', (evt, propertyName, newValue) => {
console.log(`Heading command enabled: ${newValue}`);
});The HeadingCommand automatically tracks the current heading state:
Value Property:
'heading1', 'heading2', etc.) when in a headingfalse when in a paragraph or other non-heading elementIsEnabled Property:
true when the command can be executed (valid selection)false when the command cannot be executed (invalid context)// Example state tracking:
// User selects text in an h2 element:
console.log(headingCommand.value); // 'heading1' (assuming heading1 maps to h2)
console.log(headingCommand.isEnabled); // true
// User selects text in a paragraph:
console.log(headingCommand.value); // false
console.log(headingCommand.isEnabled); // true
// User selects an unsupported element:
console.log(headingCommand.value); // false
console.log(headingCommand.isEnabled); // falseThe execute() method applies heading formats to the current selection:
Single Block Selection:
Multiple Block Selection:
Mixed Selection:
// Example executions:
// Before: <paragraph>Selected text|</paragraph>
editor.execute('heading', { value: 'heading1' });
// After: <heading1>Selected text|</heading1>
// Before:
// <paragraph>First block|</paragraph>
// <heading2>Second block</heading2>
editor.execute('heading', { value: 'heading3' });
// After:
// <heading3>First block|</heading3>
// <heading3>Second block</heading3>
// Convert heading back to paragraph:
editor.execute('heading', { value: 'paragraph' });The command works with the model elements defined in the heading configuration:
// Default model elements:
const defaultModelElements = ['paragraph', 'heading1', 'heading2', 'heading3'];
// Custom model elements:
const customConfig = {
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'title', view: 'h1', title: 'Title', class: 'ck-heading_title' },
{ model: 'subtitle', view: 'h2', title: 'Subtitle', class: 'ck-heading_subtitle' }
]
}
};
// Command will support: ['paragraph', 'title', 'subtitle']
editor.execute('heading', { value: 'title' });
editor.execute('heading', { value: 'subtitle' });The HeadingCommand is used by both UI components:
HeadingUI Dropdown:
HeadingButtonsUI Buttons:
// UI component integration example:
// When user clicks "Heading 1" in dropdown:
// → editor.execute('heading', { value: 'heading1' });
// When user clicks the heading1 button:
// → editor.execute('heading', { value: 'heading1' });
// UI components update their state based on:
// → headingCommand.value and headingCommand.isEnabledThe command includes validation and error handling:
// Error handling examples:
editor.execute('heading', { value: 'invalidHeading' }); // Ignored - invalid value
// In a context where headings aren't allowed:
console.log(headingCommand.isEnabled); // false
editor.execute('heading', { value: 'heading1' }); // No effect