Content Manipulation Commands
When to Use
You need to update, add, remove, or rearrange DOM content from AJAX callbacks.
Decision
| Command | Operation | Key Difference |
|---|---|---|
| ReplaceCommand | Replaces the entire element | New content MUST include the wrapper ID |
| HtmlCommand | Replaces inner HTML only | Wrapper element stays intact |
| AppendCommand | Adds inside element, after existing content | For lists, infinite scroll, chat |
| PrependCommand | Adds inside element, before existing content | For most-recent-first displays |
| BeforeCommand | Inserts before element (sibling) | Target element unchanged |
| AfterCommand | Inserts after element (sibling) | Target element unchanged |
| RemoveCommand | Removes element from DOM | Permanently removes; detaches behaviors |
| InsertCommand | Uses #ajax['method'] from triggering element |
3rd param is $settings, not insertion method |
Command: ReplaceCommand
Description: Replaces an entire element with new content (most common command).
Pattern:
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
$response = new AjaxResponse();
$response->addCommand(new ReplaceCommand('#target', '<div id="target">New content</div>'));
return $response;
Gotchas:
- New content MUST include the wrapper ID being replaced
- Replaces outer element; use HtmlCommand to replace inner HTML only
- Attached JavaScript behaviors automatically re-attach to new content
Command: HtmlCommand
Description: Replaces the inner HTML of an element without replacing the element itself.
Pattern:
use Drupal\Core\Ajax\HtmlCommand;
$response->addCommand(new HtmlCommand('#target', 'New inner HTML'));
Gotchas:
- Keeps the wrapper element intact, only changes contents
- Faster than ReplaceCommand when wrapper doesn't need updating
- Doesn't require wrapper ID in replacement content
Command: AppendCommand
Description: Adds content inside an element, after existing content.
Pattern:
use Drupal\Core\Ajax\AppendCommand;
$response->addCommand(new AppendCommand('#list', '<li>New item</li>'));
Gotchas:
- Adds content as last child inside the element
- Useful for infinite scroll, dynamic lists, chat messages
- Can cause memory issues if appending infinitely without cleanup
Command: PrependCommand
Description: Adds content inside an element, before existing content.
Pattern:
use Drupal\Core\Ajax\PrependCommand;
$response->addCommand(new PrependCommand('#notifications', '<div class="notification">New alert</div>'));
Gotchas:
- Adds content as first child inside the element
- Good for most-recent-first displays (notifications, comments)
Command: BeforeCommand
Description: Inserts content before an element (as a sibling, not child).
Pattern:
use Drupal\Core\Ajax\BeforeCommand;
$response->addCommand(new BeforeCommand('#target', '<p>Before target</p>'));
Gotchas:
- Inserts at same DOM level as target, not inside it
- Target element remains unchanged
Command: AfterCommand
Description: Inserts content after an element (as a sibling, not child).
Pattern:
use Drupal\Core\Ajax\AfterCommand;
$response->addCommand(new AfterCommand('#target', '<p>After target</p>'));
Gotchas:
- Inserts at same DOM level as target, not inside it
- Target element remains unchanged
Command: RemoveCommand
Description: Removes an element from the DOM.
Pattern:
use Drupal\Core\Ajax\RemoveCommand;
$response->addCommand(new RemoveCommand('#remove-me'));
Gotchas:
- Permanently removes element; can't be updated afterward
- Detaches JavaScript behaviors before removal (prevents memory leaks)
- Multiple selectors supported: removes all matching elements
Command: InsertCommand
Description: Generic insertion command. When triggered by a form element, uses the element's #ajax['method'] value to determine how content is inserted. Returns method: null in the JSON response — the JavaScript side resolves the method from the original request context.
Pattern:
use Drupal\Core\Ajax\InsertCommand;
// Selector and content; 3rd param $settings is for JS behavior settings, NOT insertion method.
$response->addCommand(new InsertCommand('#target', $render_array));
Gotchas:
- The 3rd constructor parameter is
$settings(JS behavior data) — there is NO method parameter; passing['method' => 'append']does nothing for insertion behavior - To explicitly choose a DOM insertion method in an AjaxResponse, use the specific command classes (AppendCommand, PrependCommand, etc.) — those map to named jQuery operations
- InsertCommand is most useful for form element callbacks where the method is already encoded in the triggering element's
#ajax['method'] - Source:
core/lib/Drupal/Core/Ajax/InsertCommand.php
Common Mistakes
- Using ReplaceCommand without wrapper ID in new content → Element disappears, no errors shown
- Not rendering arrays properly → Pass render arrays through
\Drupal::service('renderer')->render()before adding to commands - Forgetting to create AjaxResponse object → Attempting to add commands to render array won't work
- Chaining commands in wrong order → Commands execute in order added; replace before append, etc.
- Not sanitizing user input in commands → XSS vulnerability; always use render arrays or proper escaping
See Also
- Next: CSS Styling Commands
- Feedback Commands
- Reference:
core/lib/Drupal/Core/Ajax/(all command classes)