Tuesday, March 18, 2014

Create your Custom Content Type Picker Tree using REST

This is a simple article where you can create your own Content Type Tree view picker. 
I had the need to create a Content Type tree view picker when i was making a reference in my Custom Action solution "SharePoint 2013: Manage User Custom Actions App and Sandbox".
When we are creating a User Custom Action we can define wish Content Type will be associated. 
This can be very useful when we are creating Custom Ribbon to be associated at General Lists or specific Lists. 
In the near future i will create a article talking about the Ribbons and how we can manage using SharePoint Apps.
The Out of the Box steps to identify a Content Type ID is somehow hard or need to use some external tool like "SharePoint Client Browser for SharePoint 2010 and 2013" or "SharePoint Manager" or Powershell, here is a little description on how to get Ctype ID in the SharePoint Sites.

How to get Content Type ID using SharePoint Out of Box (example with a List):
  • Access to your  SharePoint List 
  • Access to List Settings
  • In "General Settings" > select "Advanced Settings"
  • Check "Allow management of content types?" to Yes


  • Select the Content Type "Item"
  • In the Url get the parameter "ctype", there should be the CT associated to the List



If you need more info about Content Types here you have some official links:
Content Type IDs

For testing purpose i have used JSTree plugin to create my tree view (you can Json Data to load the tree). 
PS: this JSTree plugin it is really complete and very well documented.

The main goal is to get the Content Types of the Site and Lists  (excluding the Hidden CT) as a Treeview and return to a Textbox.
Here a image example of the final output of the CT Picker.


How the solution Works 

The main goal is to create a Button that makes a call to a Modal Dialog to a Page that returns the Content Types of the Web and List as a Treeview. 


This solution have files to support the custom Content Type Picker: 

Page
  • CTPicker.aspx
Scripts
  • Jquery.js
  • jstree.js
  • Custom.js (where will be made the REST Calls or you can embedded in page)
Content
  • jstree.css
Create Content Type Picker Page

Create a Custom CTPicker.aspx page that has the controls for SharePoint Page and make the reference to the supporting files described before.



Create Content Type Picker Button and TextBox

Add the Button Picker "Browser" to Content Type Picker Page using Modal Dialog and Textbox where return the ID of the selected Content Type, for this you add a Script Script Editor Web Part and add the following example code;


Example Code:

<script>
function CTPickerDialog() {
    var options = {
        url: '../Shared%20Documents/CTPicker.aspx',
        title: 'Content Type Picker',
        showClose: true,
        showMaximized: true,
        allowMaximize: true,
        dialogReturnValueCallback: CloseCTPickerCallback
    };
    SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', options);
}
function CloseCTPickerCallback(result, target) {
    if (result == SP.UI.DialogResult.OK) {
        document.getElementById('URLTextBox').value = target;
    }
}
</script>
       <input type="submit" class="ms-input" value="Browser" id="BtnBrowseCTLocation" onclick="CTPickerDialog(); return false;" />


This code will open a modal dialog where you can select the existing content types in the existing Web.



Here is the example code to access your Content Types using REST:

<script>
$(document).ready(function () {
    LoadCTPicker();
});
function GetCurrentWebUrl() {
    return _spPageContextInfo.webServerRelativeUrl + ((_spPageContextInfo.webServerRelativeUrl.indexOf('/', _spPageContextInfo.webServerRelativeUrl.length - 1) !== -1) ? '' : '/');
}
function LoadCTPicker() {
    try {
        $('#CTPickerTree').on('select_node.jstree'function (e, data) {
            if (data.node.parent == "CT") {
                SP.UI.ModalDialog.commonModalDialogClose(1, data.node.id);
            }
            else if (data.node.parents.length == 4) {
                if (data.node.parents[1] == "Lists") {
                    SP.UI.ModalDialog.commonModalDialogClose(1, data.node.id);
                }
            }
        }).jstree(
           {
               "core":
                     {
                         "animation": 0,
                         "check_callback"true'data': [{
                             "id""Web""text": _spPageContextInfo.webTitle, "icon""../_layouts/15/images/smt_icon.gif?rev=32"'state': { 'selected'false'opened'true }, "children": [
                                 { "id""CT""text""Content Type""icon""../_layouts/15/images/pageLayoutHS.png"'state': { 'selected'false'opened'false } },
                                 { "id""Lists""text""Lists""icon""../_layouts/15/images/itgen.png?rev=26"'state': { 'selected'false'opened'false } }
                             ]
                         }]
                     }, "plugins": ["search""state""wholerow"]
           });

        RestLoad('CT');
        RestLoad('Lists');
    } catch (e) {
        SP.UI.Notify.addNotification('Request failed. ' + e.get_message() + '\n' + e.get_stackTrace(), false);
    }
}

function RestLoad(IDCT) {
    var webUrl = GetCurrentWebUrl();
    var Resturl = '';
    var CTID = '';
    var CTName = '';
    var CTImg = '';
    if (IDCT == 'CT') {
        Resturl = webUrl + "_api/web/ContentTypes?$select=Name,Id,Group&$orderby=Name&$filter=Group ne '_Hidden'";
    } else if (IDCT == 'Lists') {

        Resturl = webUrl + "_api/web/Lists?$select=Title,Id,ImageUrl";
    } else {
        Resturl = webUrl + "_api/web/Lists('" + IDCT + "')/ContentTypes?$select=Id,Name,Group&$filter=Group ne '_Hidden'"
    }

    $.ajax({
        url: Resturl,
        method: "GET",
        headers: { "Accept""application/json; odata=verbose" },
        success: function (data) {
            var TreePicker = $('#CTPickerTree').jstree(true);
            var ListsNode = TreePicker.get_node(IDCT);
            var jsonObject = data.d.results;
            for (var i = 0; i < jsonObject.length; i++) {
                if (IDCT == 'Lists') {

                    CTID = jsonObject[i].Id;
                    CTName = jsonObject[i].Title;
                    CTImg = jsonObject[i].ImageUrl;
                }
                else {
                    CTID = jsonObject[i].Id.StringValue;
                    CTName = jsonObject[i].Name + "(" + jsonObject[i].Group + ")";
                    CTImg = "../_layouts/15/images/pageLayoutHS.png";
                }
                TreePicker.create_node(ListsNode, {
                    id: CTID, text: CTName, icon: CTImg
                });
                if (IDCT == 'Lists') {
                    RestLoad(CTID);
                }
            }
        },
        error: function (xhr) {
            SP.UI.Notify.addNotification(xhr.status + ': ' + xhr.statusText, false);
        }
    });
}
</script>

Return Content Type Value to TextBox

After the selection of the Content Type the Modal Dialog is closed and returns the ID, for this case (0x0101).

Code Example:
 if (data.node.parent == "CT") {
                SP.UI.ModalDialog.commonModalDialogClose(1, data.node.id);
            }
            else if (data.node.parents.length == 4) {
                if (data.node.parents[1] == "Lists") {
                    SP.UI.ModalDialog.commonModalDialogClose(1, data.node.id);
                }
            }

Output of the Content Type selection:



With a little code and REST Call’s we can make a simple tree View J

Hope you like this article,
Kind regards, 

André Lage
Post a Comment