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.
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)); }