Hiding the out-of-the-box Document Library in SharePoint 2013

Recently I was tasked with investigating the possibility of removing the out of the box Document Library from the ‘add an app’ page so that users wouldn’t accidentally select that option instead of a specific list template containing the organisation’s meta data they want included in the library. It’s been refreshing exploring Intranet-style scenarios after having focussed on public facing web sites for so long and as such this is the type of problem I was eager to get my head around and solve.

In days gone by one would generally turn to creating a custom site definition to achieve such a goal – or god forbid modify one of the out of the box site definitions. We’ve all known for some time that the latter is a terrible idea, but the former isn’t particularly better when considering future migrations. It was no surprise however that it was still one of the first options I came across when researching solutions, such as on Salaudeen Rajack’s post Hide Site templates & List Templates in SharePoint. Back to the drawing board.

Another more promising option I pursued was using PowerShell to disable the feature which specifically provisions the Document Library as per Renan Rocha’s Hide “list template” disabling its feature or this StackOverflow question: Hide Listtemplate from Create Dialog in PowerShell. This worked, however it also removed a custom document library template which I had created for testing purposes to mirror the desired result I’d want to end up with. It also only worked at the web layer, which means that we’d first need to run it recursively across the whole site, then would also need to run it each time a new sub site was created – not exactly practical even if it did suit our purpose.

There were also a few hacky options I discovered along the way which I was obviously keen to avoid, such as that listed on the MSDN question: Is it possible to delete the default document library template?. I figured there had to be a better way.

I decided to change tack a little bit and investigate adding our custom templates as ‘Noteworthy’ apps to at least give them some prominence on the screen. Unfortunately it turned out that while you can set Apps as noteworthy by making them featured apps, you can’t set list templates as featured or noteworthy. There are some good posts on this topic including Stephen Brown’s SharePoint 2013 and the Noteworthy section and Shereen Qumsieh’s Making Changes to the Noteworthy Section of a SharePoint Site. It was these posts that gave me all the information I needed to solve my problem.

I ended up creating a Delegate control targeting AdditionalPageHead (yes this was a full trust solution – I’m sure someone can come up with an alternative way of getting this to work in Office 365!) to run the following JavaScript:

<script type="text/javascript">
    function AlterStorefront() {
        if (SP.Storefront != undefined) {
            var listedApps = SP.Storefront.StorefrontApp.get_currentView();
            if (listedApps == undefined || listedApps.$2i_3 == null || listedApps.$L_3 == null) { setTimeout(AlterStorefront, 750); return; }
			
            listedApps.$2i_3.length = 0;

            for (i = 0; i < listedApps.$L_3.length; i++) {
                if (listedApps.$L_3[i].$2Q_0.Title == "Document Library") {
                    listedApps.$L_3.splice(i, 1);
                }
                if (listedApps.$L_3[i].$2Q_0.Title.indexOf("Insite") > -1 || listedApps.$L_3[i].$2Q_0.Title == "Icon Links Grid") {
                    listedApps.$2i_3.push(listedApps.$L_3[i]);
                }
            }

            SP.Storefront.StorefrontApp.get_currentView().updateUI();
        }
    }

    SP.SOD.executeFunc("sp.js", "SP.Storefront", AlterStorefront);
</script>

While AdditionalPageHead exists on all pages, checking that SP.Storefront exists means that it won’t run on every page.

So the first point of note is that we wait until SP.js has loaded before calling our function given it relies on it. Once we’ve confirmed the Storefront does exist on the current page, we attempt to get the current view of the Storefront. Because this loads asynchronously itself, it is highly probable that it hasn’t loaded before this code executes. As such I performed a few checks to ensure the properties of note had completely loaded and re-called the function after sleeping for a period of time (0.75 seconds I found to be roughly the most optimal on my development server).

The next step was clearing out the existing Noteworthy apps by setting the array’s length to 0. This perhaps isn’t ideal given your ‘Featured’ apps would also be wiped rather than just the default ones that populate that area, however if this is a concern you can more specifically target their removal similar to how I did it in the next step.

That next step is looping through the array which stores all the app items. We look for the one corresponding with ‘Document Library’ and remove it using splice. We then look for a particular string (or multiples) to identify the templates we want to promote to Noteworthy, and add them to that array. The final step is to update the UI to reflect those changes.

One important thing to note is that the indexOf function is not compatible with IE7 and IE8 – if this is a problem then you may want to ‘find’ the apps for promotion another way.

So there you have it, a semi (not-so?) elegant way of achieving the desired result – removing the Document Library list template from the ‘add an app’ page and replacing the noteworthy items with your custom templates. The solution isn’t perfect – unfortunately there is a visual delay between loading the initial page (which you see for a moment) and when the updateUI kicks in – but overall it does the job.

5 Responses to Hiding the out-of-the-box Document Library in SharePoint 2013

  1. Sylvain Jourdan says:

    Hi.
    Many thanks for sharing your solution to managing this page. It really helped me.

    By the way, i’ve noticed a problem. Your script is loading on the page load only.
    If you’re making an app research in the searchbox above and then go back to your apps list, your script won’t be executed and your changes will be lost.

    So i’l sharing my piece of code. The goal is to remove the “Import Spreadsheet” app which is not a list template that you can remove by desactivating a feature.

    function RefreshUI() {
    var listedApps = SP.Storefront.StorefrontApp.get_currentView();
    if (listedApps.$L_3 != null)
    {
    for (i = 0; i -1) {
    listedApps.$L_3.splice(i, 1);
    }
    }

    SP.Storefront.StorefrontApp.get_currentView().updateUI();
    }

    }

    function AlterStorefront() {
    if (SP.Storefront != undefined) {
    var listedApps = SP.Storefront.StorefrontApp.get_currentView();

    if (listedApps == undefined) { setTimeout(AlterStorefront, 750); return; }
    listedApps.spProxy.add_getAppsCompleted(RefreshUI);

    RefreshUI();
    }
    }

    SP.SOD.executeFunc(“sp.js”, “SP.Storefront”, AlterStorefront);

    As you can see, my scrpt is executed everytime the getAppsCompleted is fired.

    Thanks again for sharing

  2. John says:

    can you provide some instruction on how to implement this? Thanks

  3. Mikael says:

    Hi,

    I have a javascript snip that works on Sharepoint 2013 for this, but not anymore for Sharepoint 2016.
    This is the place where it goes wrong; $2i_3 and $L_3 are both null:

    if (listedApps == undefined || listedApps.$2i_3 == null || listedApps.$L_3 == null)

    –> Any ideas how to fix it for Sharepoint 2016?

    • Matt says:

      Hi Mikael. I haven’t had to implement this in 2016 so not off the top of my head. Personally I’d just start exploring the JavaScript objects in the console window, put breakpoints in the code, see what exists. If you can find the relevant objects you should be able to manipulate them.

Leave a comment