Working with Content Types in the JavaScript Client Object Model

Some things that should be simple are made more difficult in the Client Object Model because of the asynchronous manner in which it works. The Client Object Model does not interact directly with SharePoint’s data – it is really a wrapper for web service calls that send and receive messages from SharePoint. So in order to do anything with the CSOM, you need to send a request to the web service, wait for the response, and then act on it.

A prime case is Content Types. Suppose you had a list with multiple Content Types, and you need to fetch an item and determine its Content Type. You might think you could do something like this:

Var ct = listItem.get_item("Content Type");

Well, there is no such property available in the CSOM object. You could Fiddle the web service response JSON of a simple query like this and you would not see the Content Type’s name anywhere, so there’s no chance the CSOM will be able to get that data. There is, however, and object called ContentTypeId which has a property containing the Content Type’s ID.

In order to get the name of the list item’s Content Type, here’s what we need to do: We need to explicitly query the list’s Content Types collection, load it into the context object, and loop through the collection until we find the one whose ID matches the ContentTypeID we’ve found earlier.

Note: Sometimes it’s not so obvious when we need to call load() on an object when querying the Client Object Model. Here is a rule of thumb I have developed: For “loose” properties, you generally do not need to explicitly load them, but for collections of objects, you need to call load on them. For example, a collection of Content Types on a list, or a collection of Lists in a Web object, must be loaded into the context object explicitly.

The code to do this would look something like this:

//couple of global variables
var listItem = null;
var listContentTypes = null;

function getContentTypeOfCurrentItem(id) {
    var clientContext = new SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle("Projects");

    //get the list item and load() it
    listItem = oList.getItemById(id);
    clientContext.load(listItem);

    //get the content types and load the collection
    listContentTypes = oList.get_contentTypes();
    clientContext.load(listContentTypes);

    clientContext.executeQueryAsync(Function.createDelegate(this, getContentTypeOfCurrentItemSucceeded), Function.createDelegate(this, onQueryFailed));
}

//the callback
function getContentTypeOfCurrentItemSucceeded(sender, args) {    
    var ctid = listItem.get_item("ContentTypeId").toString();

    var ct_enumerator = listContentTypes.getEnumerator();
    while (ct_enumerator.moveNext()) {
        var ct = ct_enumerator.get_current();

        if (ct.get_id().toString() == ctid) {
            //we've got our content type, now let's get its name
            var contentTypeName = ct.get_name();
        }
    }
}

Setting the Content Type on a new list item

Setting the Content Type on a newly created list item works in about the same manner. You query the collection of Content Types, loop through them to find the one you want, get its ID and pass that ID into the new item using set_item():

var projectList;
function getContentTypeOfCurrentItem(id) {
    var clientContext = new SP.ClientContext.get_current();
    projectList = clientContext.get_web().get_lists().getByTitle("Projects");
    clientContext.load(projectList);

    //get the content types and load the collection
    listContentTypes = oList.get_contentTypes();
    clientContext.load(listContentTypes);

    clientContext.executeQueryAsync(Function.createDelegate(this, getContentTypeOfCurrentItemSucceeded), Function.createDelegate(this, onQueryFailed));
}

function getContentTypeOfCurrentItemSucceeded() {
    var CTID;

    var ct_enumerator = listContentTypes.getEnumerator();
    while (ct_enumerator.moveNext()) {
        var ct = ct_enumerator.get_current();
        if (ct.get_name() == ctName) {
            CTID = ct.get_id();           
        }
    }
   
    var newProjectInfo = new SP.ListItemCreationInformation();
    var newProject = reviewTasksList.addItem(newProjectInfo);
    newProject.set_item('Title', "Foo list item");
    newProject.set_item('ContentTypeId', CTID);
    //set other fields
    newProject.update();
    clientContext.load(newProject);

    clientContext.executeQueryAsync(Function.createDelegate(this, this.SomeCallbackIhaveNotDefined), Function.createDelegate(this, this.queryFailed));
}