<p>Many of those advanced endpoints are undocumented, but you can find out a lot with the devtools. If you use the <em>Delete (with Descendants)</em> option in the backend and check the devtools, you can see it uses <a href="https://docs.craftcms.com/api/v3/craft-controllers-elementindexescontroller.html#public-methods" rel="nofollow noreferrer">craft\controllers\ElementIndexesController::actionPerformAction</a>. This method expects an <code>elementAction</code> parameter to tell it which action to perform. You can pass <code>craft\\elements\\actions\\Delete</code> which includes the <code>withDescendants</code> option you're looking for. The payload for the request will also tell you which parameters the action requires:</p>
<p><a href="https://i.sstatic.net/ATZzZ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/ATZzZ.png" alt="Screenshot of the payload for the perform action endpoint" /></a></p>
<p>Check the source code of the <a href="https://github.com/craftcms/cms/blob/develop/src/controllers/ElementIndexesController.php#L172" rel="nofollow noreferrer"><code>actionPerformAction</code> method</a> and the <a href="https://github.com/craftcms/cms/blob/develop/src/elements/actions/Delete.php" rel="nofollow noreferrer"><code>craft\elements\actions\Delete</code> class</a> to find which parameters you can use and which formats they can take. Then you can construct a frontend form with (hidden) inputs to perform this action for a particular element.</p>
<p>Adding the parameters inside a form (with <code>method=&quot;POST&quot;</code>) can be done using the <a href="https://craftcms.com/docs/3.x/dev/functions.html#hiddeninput" rel="nofollow noreferrer"><code>hiddenInput</code> Twig function</a>:</p>
<pre class="lang-twig prettyprint-override"><code>{{ hiddenInput('elementAction', 'craft\\elements\\actions\\Delete') }}
{{ hiddenInput('elementType', 'craft\\elements\\Entry' }}
{{ hiddenInput('source', &quot;section:#{entry.section.uid}&quot; }}
{{ hiddenInput('withDescendants', true) }}
</code></pre>
<p>Check the request in the devtools as mentioned above as well as the source code for the controller endpoint and the action class to find out which parameters are required. For this action in particular, it looks like it requires <code>criteria</code> for the query, and an array of <code>elementIds</code> to delete. Some parameters may also be optional. Make sure to check the source code for dependencies between parameters as well. For example, it looks like the action <a href="https://github.com/craftcms/cms/blob/develop/src/elements/actions/Delete.php#L157" rel="nofollow noreferrer">will <em>not</em> delete any descendants</a> if you specify <code>hard: true</code> to hard-delete the elements instead of soft-deleting them.</p>

CC BY-SA 4.0
2021-12-06T17:26:10.667Z
Thanks so much for the detailed response MoritzLost. That's really useful information to help me learn how to approach this. Would you have any examples of how that would be constructed? Or something along similar lines? I'm relativity new to something as complex as this. Thanks!
Kieron Keenan
CC BY-SA 4.0
2021-12-07T10:57:05.570Z
@KieronKeenan Basically, you need to use visible and/or hidden inputs in your form to include the data the controller requires to perform the requested action. The same way you're using `{{ hiddenInput('entryId', entry.id) }}` to pass the entryId to the `delete-entry` action, you can, for example, specify the `source` for the action: `{{ hiddenInput('source', "section:#{entry.section.uid}") }}`. Then it's just a matter of checking the request in the devtools and/or the source code to see which parameters the controller and the action require and adding those to the form.
MoritzLost
CC BY-SA 4.0
2021-12-07T11:04:24.453Z
@KieronKeenan I've updated my answer with a code example.
MoritzLost
CC BY-SA 4.0
2021-12-08T10:07:01.593Z
Thanks so much for the help and guidance here. I'm relatively new to Craft so this has been quite challenging for me. I'm still trying to work through the problem with your advice but still unsure what the root cause/causes that's stopping the form from deleting the parent + children entries.
Kieron Keenan
CC BY-SA 4.0
2021-12-08T10:08:04.023Z
this is basically what I've been trying to test out... 

`<form method="post" accept-charset="UTF-8">
    {{ csrfInput() }}
    {{ hiddenInput('elementType', 'craft\\elements\\Entry') }}
    {{ hiddenInput('elementAction', 'craft\\elements\\actions\\Delete') }}
    {{ hiddenInput('deletedElementIds', entry.id) }}
    {{ hiddenInput('hard', false) }}
    {{ hiddenInput('source', "section:#{entry.section.uid}") }}
    {{ hiddenInput('withDescendants', true) }}
    {{ redirectInput(entry.parent.url) }}

    <input type="submit" class="button" value="Delete">
  </form>`
Kieron Keenan
CC BY-SA 4.0
2021-12-08T10:24:08.563Z
@KieronKeenan Please post your partial code as a formatted code block in your question, it's unreadable in the comments. Where are you getting the `deletedElementIds` parameter from? I only see that as a variable appearing in the delete action, but not as a POST parameter. Looks like you're still missing some parameters – `criteria`, `context` and `elementIds` in particular. If you can't get it to work, another option would be to build your own controller endpoint that just accepts an element ID and uses the `Elements` service directly to delete the specified element and all it's descendants.
MoritzLost
CC BY-SA 4.0
2021-12-08T10:25:28.473Z
@KieronKeenan The `elementIds` parameter is required – see [this line in the source code](https://github.com/craftcms/cms/blob/develop/src/controllers/ElementIndexesController.php#L179).
MoritzLost
CC BY-SA 4.0
2021-12-08T10:30:01.953Z
@KieronKeenan Some post parameters are also retrieved in the [`beforeAction` method of the controller](https://github.com/craftcms/cms/blob/b26caca81f2b88051c6e37d99be70a91e515274d/src/controllers/ElementIndexesController.php#L83-L110), make sure to check those as well and include them in your form if necessary.
MoritzLost
CC BY-SA 4.0
2021-12-10T12:10:48.547Z
Thanks @MoritzLost! I think I'm in way above my head here trying to figure this out but I really do appreciate the support & advice here. I'll keep going at it till I get it working.
Kieron Keenan
CC BY-SA 4.0
2021-12-06T10:24:54.197Z
2021-12-08T10:22:58.793Z
2021-12-08T10:22:58.793Z
MoritzLost
<p>I'm having some trouble solving this issue and could do it with some help. Basically, I'm looking to replicate the &quot;Delete (with descendants)&quot; function from the admin panel in a front-end form.</p>
<p>On the front-end at the moment users can delete children or parent pages, but not the parent (and children automatically). I've tried a number of different methods but to no avail.</p>
<p>My front-end is using...</p>
<pre><code>       &lt;form method=&quot;post&quot; accept-charset=&quot;UTF-8&quot; id=&quot;delete-page&quot;&gt;
          {{ csrfInput() }}
          {{ hiddenInput('context', 'index') }}
          {{ hiddenInput('criteria', '') }}
          {{ hiddenInput('elementAction', 'craft\\elements\\actions\\Delete') }}
          {{ hiddenInput('elementIds', entry.id) }}
          {{ hiddenInput('elementType', 'craft\\elements\\Entry') }}
          {{ hiddenInput('hard', false) }}
          {{ hiddenInput('source', &quot;section:#{entry.section.uid}&quot;) }}
          {{ hiddenInput('withDescendants', true) }}
          &lt;input type=&quot;submit&quot; class=&quot;button&quot; class=&quot;save&quot; value=&quot;Delete P+C&quot; accesskey=&quot;v&quot;&gt;
      &lt;/form&gt;
</code></pre>
<p>In the Craft Docs, I came across <a href="https://docs.craftcms.com/api/v3/craft-elements-actions-delete.html#withdescendants" rel="nofollow noreferrer">withDescendants</a> but not sure how to utilize this on the front-end.</p>
<p>Any advice here?</p>

<frontend><frontend-form><children><delete>
Delete Parent and Children via the frontend
# Delete Parent and Children via the frontend

(Asked by: username_0 on 2021-12-04)

I'm having some trouble solving this issue and could do it with some help. Basically, I'm looking to replicate the "Delete (with descendants)" function from the admin panel in a front-end form.
On the front-end at the moment users can delete children or parent pages, but not the parent (and children automatically). I've tried a number of different methods but to no avail.
My front-end is using...
       
          {{ csrfInput() }}
          {{ hiddenInput('context', 'index') }}
          {{ hiddenInput('criteria', '') }}
          {{ hiddenInput('elementAction', 'craft\\elements\\actions\\Delete') }}
          {{ hiddenInput('elementIds', entry.id) }}
          {{ hiddenInput('elementType', 'craft\\elements\\Entry') }}
          {{ hiddenInput('hard', false) }}
          {{ hiddenInput('source', "section:#{entry.section.uid}") }}
          {{ hiddenInput('withDescendants', true) }}
          
      

In the Craft Docs, I came across withDescendants but not sure how to utilize this on the front-end.
Any advice here?

**Tags:** frontend, frontend-form, children, delete


---

## 1 answers

### Answer by username_1 on 2021-12-06. Score: 1

Many of those advanced endpoints are undocumented, but you can find out a lot with the devtools. If you use the Delete (with Descendants) option in the backend and check the devtools, you can see it uses craft\controllers\ElementIndexesController::actionPerformAction. This method expects an elementAction parameter to tell it which action to perform. You can pass craft\\elements\\actions\\Delete which includes the withDescendants option you're looking for. The payload for the request will also tell you which parameters the action requires:

Check the source code of the actionPerformAction method and the craft\elements\actions\Delete class to find which parameters you can use and which formats they can take. Then you can construct a frontend form with (hidden) inputs to perform this action for a particular element.
Adding the parameters inside a form (with method="POST") can be done using the hiddenInput Twig function:
{{ hiddenInput('elementAction', 'craft\\elements\\actions\\Delete') }}
{{ hiddenInput('elementType', 'craft\\elements\\Entry' }}
{{ hiddenInput('source', "section:#{entry.section.uid}" }}
{{ hiddenInput('withDescendants', true) }}

Check the request in the devtools as mentioned above as well as the source code for the controller endpoint and the action class to find out which parameters are required. For this action in particular, it looks like it requires criteria for the query, and an array of elementIds to delete. Some parameters may also be optional. Make sure to check the source code for dependencies between parameters as well. For example, it looks like the action will not delete any descendants if you specify hard: true to hard-delete the elements instead of soft-deleting them.

> **Comments:**
> **username_0**: Thanks so much for the detailed response username_1. That's really useful information to help me learn how to approach this. Would you have any examples of how that would be constructed? Or something along similar lines? I'm relativity new to something as complex as this. Thanks!  
> **username_1**: @KieronKeenan Basically, you need to use visible and/or hidden inputs in your form to include the data the controller requires to perform the requested action. The same way you're using `{{ hiddenInput('entryId', entry.id) }}` to pass the entryId to the `delete-entry` action, you can, for example, specify the `source` for the action: `{{ hiddenInput('source', "section:#{entry.section.uid}") }}`. Then it's just a matter of checking the request in the devtools and/or the source code to see which parameters the controller and the action require and adding those to the form.  
> **username_1**: @KieronKeenan I've updated my answer with a code example.  
> **username_0**: Thanks so much for the help and guidance here. I'm relatively new to Craft so this has been quite challenging for me. I'm still trying to work through the problem with your advice but still unsure what the root cause/causes that's stopping the form from deleting the parent + children entries.  
> **username_0**: this is basically what I've been trying to test out...   `<form method="post" accept-charset="UTF-8">     {{ csrfInput() }}     {{ hiddenInput('elementType', 'craft\\elements\\Entry') }}     {{ hiddenInput('elementAction', 'craft\\elements\\actions\\Delete') }}     {{ hiddenInput('deletedElementIds', entry.id) }}     {{ hiddenInput('hard', false) }}     {{ hiddenInput('source', "section:#{entry.section.uid}") }}     {{ hiddenInput('withDescendants', true) }}     {{ redirectInput(entry.parent.url) }}      <input type="submit" class="button" value="Delete">   </form>`  
> **username_1**: @KieronKeenan Please post your partial code as a formatted code block in your question, it's unreadable in the comments. Where are you getting the `deletedElementIds` parameter from? I only see that as a variable appearing in the delete action, but not as a POST parameter. Looks like you're still missing some parameters – `criteria`, `context` and `elementIds` in particular. If you can't get it to work, another option would be to build your own controller endpoint that just accepts an element ID and uses the `Elements` service directly to delete the specified element and all it's descendants.  
> **username_1**: @KieronKeenan The `elementIds` parameter is required – see [this line in the source code](https://github.com/craftcms/cms/blob/develop/src/controllers/ElementIndexesController.php#L179).  
> **username_1**: @KieronKeenan Some post parameters are also retrieved in the [`beforeAction` method of the controller](https://github.com/craftcms/cms/blob/b26caca81f2b88051c6e37d99be70a91e515274d/src/controllers/ElementIndexesController.php#L83-L110), make sure to check those as well and include them in your form if necessary.  
> **username_0**: Thanks @username_1! I think I'm in way above my head here trying to figure this out but I really do appreciate the support & advice here. I'll keep going at it till I get it working.  

---

