Sitecore – Delete Selected SubItems v2

Following last year’s blog Delete Selected SubItems, in today’s article, I will be talking about some of the changes that I have done to improve the module. The latest code can be found on my GitHub repository implemented on Sitecore 10, however it does work on both Sitecore 9 as well. So let’s get right into it.

Improvements

Below is the list of improved features that I have added/changed:

  1. Select All and Deselect All options
    The most important improvement over the version 1. These two options have been added so as to allow Content Authors to easily select all or deselect all sub Items to delete. For example, if ever you have 100 sub Items and you need to delete 70 Items, you can select all and then unselect the other 30 Items instead of selecting Items to be deleted 70 times.
  2. Hide custom menu item
    A known issue from the first version, the custom menu item `Delete Selected subitems` will be hidden, if ever an Item does not have any subItems.
  3. Multilist instead of Treelist
    The reason as to why I have use a multilist instead of treelist in the new version, is because in treelist, Content Authors were able to expand subItems that had inner children of their own and it tend to slow down the process. Using a multilist, only the subItems will appear without the option of expanding them.

Sitecore Item

The same custom menu Item is used and can be found at the path /sitecore/content/Applications/Content Editor/Menues/Delete/Delete Selected Subitems in the Core Database.

Sitecore Config file and the Custom Command Class

The custom command `item:deleteselectedchildren` to call the Command class has stayed the same. The only changes in the Command class is the addition of the override method QueryState. This method is use to decide whether to display or hide the custom menu Item. Below is the preview of the method:

1
2
3
4
5
6
7
8
9
10
11
public override CommandState QueryState(CommandContext context)
        {
            var item = context.Items[0];
 
            if (item == null)
            {
                return CommandState.Hidden;
            }
 
            return item.HasChildren ? base.QueryState(context) : CommandState.Hidden;
        }

Dialog Code Explanation

DeleteSelectedChildren – Control

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="utf-8" ?>
<control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense" xmlns:content="http://www.sitecore.net/content">
  <DeleteSelectedChildren>
    <FormDialog Icon="Applications/32x32/form_yellow_edit.png" Header="Delete Options" Text="Delete the selected items.">
      <Stylesheet Key="SetBaseTemplates">
        .scContentControl {
          height:100%;
        border:none;
        }
        .scContentControlMultilistBox {
          height:100%;
        }
        .scContentControlTreelist {
        border:none;
        }
        .scContentButtons {
          padding: 0 0 10px 0;
        }
        a.scContentButton {
          color: #2694C0;
          white-space: nowrap;
          display: inline-block;
          border-right: 1px solid #ccc;
          padding: 0 14px 0 15px;
          padding-left: 15px;
        }
        .scContentButton:first-child {
            padding-left: 0;
        }
        .scContentButton:last-child {
          border-right: 0px;
        }
      </Stylesheet>
      <Script Src="/sitecore/shell/Applications/Content Manager/Content Editor.js" RunAt="server"/>
      <CodeBeside Type="SitecoreExtension.Utilities.Dialogs.SetDeleteSubItems, SitecoreExtension.Utilities"/>
 
      <VerticalTabstrip>
        <TabSection Header="Options" />      
        <Tab ID="Templates" Header="Items">
          <label>Delete Permanently: </label>    
          <content:Checkbox ID="Checkbox" Value="Edit" />
           
          <div class="scContentButtons">
            <a href="#" class="scContentButton" onclick="javascript:return scForm.postEvent(this,event,'contentmultilist:selectall(id=SubItems)')">Select all</a>
            <a href="#" class="scContentButton" onclick="javascript:return scForm.postEvent(this,event,'contentmultilist:unselectall(id=SubItems)')">Deselect all</a>
          </div>
          
          <content:MultilistEx ID="SubItems"/>
        </Tab>
      </VerticalTabstrip>
       
    </FormDialog>
  </DeleteSelectedChildren>
</control>
  • Script tag
    A <script> tag has been added, with the src attribute reads the JavaScript file found under the path /sitecore/shell/Applications/Content Manager/Content Editor.js so as to be able to read the two events ‘contentmultilist:selectall(id=SubItems)’ and ‘contentmultilist:unselectall(id=SubItems)’ when user clicks on them.
  • Multilist instead on Treelist
    The MultilistEx command is used instead of the TreeList.

SetDeleteSubItems – DialogForm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class SetDeleteSubItems : DialogForm
    {
        protected MultilistEx SubItems;
 
        protected Checkbox checkbox;
 
        protected Database database = Factory.GetDatabase("master");
        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, nameof(e));
            base.OnLoad(e);
            if (Context.ClientPage.IsEvent)
                return;
            Item itemFromQueryString = UIUtil.GetItemFromQueryString(Context.ContentDatabase);
            Assert.IsNotNull(itemFromQueryString, "Item not found.");
 
            //MultiList
            SubItems.ItemLanguage = Context.Language.Name;
            SubItems.Database = "master";
            SubItems.Source = itemFromQueryString.Paths.FullPath;
            SubItems.ItemID = itemFromQueryString.ID.ToString();
        }
 
        protected override void OnOK(object sender, EventArgs args)
        {
            Assert.ArgumentNotNull(sender, nameof(sender));
            Assert.ArgumentNotNull(args, nameof(args));
 
            var arrayItem = SubItems.GetValue().Split('|');
 
            foreach (var item in arrayItem)
            {
                Item sample = database.GetItem(new ID(item));
 
                using (new SecurityDisabler())
                {
                    if (checkbox.Checked)
                    {
                        sample.Delete();
                    }
                    else
                    {
                        sample.Recycle();
                    }
                }
            }
 
            base.OnOK(sender, args);
        }
    }

The Back-End code is more or less the same compare to the version 1. Instead of TreeList, the MultilistEx is used.

Below is the display of the Control:

You can download the Sitecore Deleted Selected SubItems-2.0.zip package here.

That’s it for today’s blog. Stay tuned for my next blog 😀

Comments