Introduction
When working with the SharePoint API via Javascript it is essential to work with the Javascript Object Model (JSOM). JSOM is the use of JavaScript with the SharePoint client side API which allows you to work with SharePoint without deploying code to the server itself. Due to SP Online relying on sand-boxed approaches, JSOM (or CSOM) is typically what would be used for code.
JSOM has a few key elements to keep in mind:
- Work is done through a ClientContext object which acts as your window to operating with SharePoint. These are tied to a specific SP site and can be instantiated to the current site as well as a different site than the user is on.
- When working with methods in the context to get such things as items or lists you will not be able to read the properties until the object is loaded. Likewise, operations are not executed until explicitly told to by calling ClientContext.executeQueryAsync.
- The context works somewhat like a queue, operations are not completed until an execute is called. Each execute represents a single call to the server. It is good practice to avoid calling execute until necessary.
Table of Contents
- General JSOM
- Fields/Columns
- List Items
- Lists
-
Web Scope
- User Groups
- Permission Check
- Property Bag
- Users
- Content Types
Note that some code needs to be examined prior to running to substitute proper values where needed. I.e. Adding a field to a list may require a pre-existing list and adjusting the script to point to that list for the example to work.
General JSOM
These are general examples on some common snippets or patterns when working with JSOM objects
Enumerating Through Collections
- Object must support getEnumerator function
var enumerator = yourObjCollection.getEnumerator(); while (enumerator.moveNext()) { var curObj = enumerator.get_current(); //i.e. alert(curItem.get_title()); }
//Targets the SPWeb the user is currently browsing var ctx = new SP.ClientContext.get_current();
//Targets the SPWeb via URL (Server Relative or Absolute) var ctx = new SP.ClientContext("/sites/yoursite"); //Use '/' for top level SPWeb at root of domain var rootDomainWeb = new SP.ClientContext("/"); //For the root web of the current site collection leverage _spPageContextInfo var curSiteColRootCtx = new SP.ClientContext(_spPageContextInfo.siteServerRelativeUrl);
Fields
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var myList = curWeb.get_lists().getByTitle('MyList'); ctx.load(myList); ctx.executeQueryAsync( function(){ //Create the field var fields = myList.get_fields() fields.addFieldAsXml('<Field ID="{c10f042e-ab13-435c-ab93-9885f0d48d02}" Name="myInternalName" DisplayName="A Multi User Column" Group="GroupName" Type="UserMulti" Mult="TRUE"></Field>', true, SP.AddFieldOptions.addToDefaultContentType) ctx.executeQueryAsync( function (){ alert('Created field!'); }, function (){ alert('Error: ' + args.get_message()); } ); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
- Person or Group (multiple OR single)
var itemId = 1; var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var listItem = customList.getItemById(itemId); ctx.load(listItem); ctx.executeQueryAsync( function(){ //People Picker Multi OR Single value var usrOutput = []; var usrGrps = listItem.get_item("PersonOrGroup"); //Multi fields return arrays, singles do not. Unify to produce array in either case. var userItems = [].concat( usrGrps ); userItems.forEach(function(userOrGroup){ usrOutput.push("Name: " + userOrGroup.get_lookupValue() + "\nID: " + userOrGroup.get_lookupId() + "\nEmail: " + userOrGroup.get_email()); }); alert(usrOutput.join("\n\n")); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var itemId = 1; var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var listItem = customList.getItemById(itemId); ctx.load(listItem); ctx.executeQueryAsync( function(){ //MMS Multi Value var mmsValues = []; var managedMeta = listItem.get_item("ManagedMetadata"); var managedMetaSingle = listItem.get_item("ManagedSingle"); //You can detect if a field is single with the following: //if(managedMetaSingle instanceof SP.Taxonomy.TaxonomyFieldValue) //Read multiple select taxonomy field var mmsEnum = managedMeta.getEnumerator(); while (mmsEnum.moveNext()) { var mmsItem = mmsEnum.get_current(); mmsValues.push('Label: ' + mmsItem.get_label() + ' Guid: ' + mmsItem.get_termGuid()); } //Read single taxonomy field mmsValues.push('Label: ' + managedMetaSingle.get_label() + ' Guid: ' + managedMetaSingle.get_termGuid()); alert(mmsValues.join("\n\n")); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
List Items
var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var itemCreateInfo = new SP.ListItemCreationInformation(); var listItem = customList.addItem(itemCreateInfo); listItem.set_item('Title', 'My Title'); listItem.update(); ctx.load(listItem); ctx.executeQueryAsync( function(){ alert('Item created: ' + listItem.get_id()); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
Creating (Advanced – All Field Types)
- Single Line of Text
- Multiple Lines of Text
- Choice
- Number and Currency
- Date and Time
- Yes/No
- Person or Group
- Hyperlink or Picture
- Lookup
- Managed Metadata (single)
var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var itemCreateInfo = new SP.ListItemCreationInformation(); var listItem = customList.addItem(itemCreateInfo); //Simple values listItem.set_item('Title', 'My Title'); listItem.set_item('SingleLineOfText', 'Single Line of Text'); listItem.set_item('MultipleLinesOfText', 'Multiple <br/><br/>lines'); listItem.set_item('Choice', 'Choice 2'); listItem.set_item('Number', '10000'); listItem.set_item('Currency', '10000.55'); listItem.set_item('DateAndTime', new Date()); listItem.set_item('YesNo', false); //'No', 'False', 0, 'Yes', 'True', 1, true, false (all work) //Users are added via their integer ID on the current site listItem.set_item('PersonOrGroup', _spPageContextInfo.userId); //URL is added by setting a FieldUrlValue object var urlVal = new SP.FieldUrlValue(); urlVal.set_url("http://www.migee.com"); urlVal.set_description("Description of Link"); listItem.set_item('HyperlinkOrPicture', urlVal); //Lookup column is set to the item ID in the list the lookup points to listItem.set_item('LookupToSelfOnTitle', 1); //For managed metadata use the term ID from MMS listItem.set_item('ManagedMetadata', "caa6bb9c-a7a1-48af-89e8-39cd77acdcff"); //Update and load new item listItem.update(); ctx.load(listItem); ctx.executeQueryAsync( function(){ console.log("added"); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var itemId = 1; var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var listItem = customList.getItemById(itemId); ctx.load(listItem); ctx.executeQueryAsync( function(){ alert('Item title: ' + listItem.get_item("Title")); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml('<View><Query><Where><Geq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>1</Value></Geq></Where></Query><RowLimit>10</RowLimit></View>'); var listItemCol = customList.getItems(camlQuery); ctx.load(listItemCol); ctx.executeQueryAsync( function(){ var listItems = []; var listEnum = listItemCol.getEnumerator(); while (listEnum.moveNext()) { var item = listEnum.get_current(); listItems.push('ID: ' + item.get_id() + ' Title: ' + item.get_item('Title')); } alert(listItems.join("\n")); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var itemId = 1; var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var listItem = customList.getItemById(itemId); listItem.set_item('Title', 'New Title'); listItem.update(); ctx.executeQueryAsync( function(){ alert('Item updated'); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var itemId = 1; var ctx = new SP.ClientContext.get_current(); var customList = ctx.get_web().get_lists().getByTitle('CustomList'); var listItem = customList.getItemById(itemId); listItem.deleteObject(); ctx.executeQueryAsync( function(){ alert('Item deleted: ' + itemId); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
Lists
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var listCreationInfo = new SP.ListCreationInformation(); listCreationInfo.set_title('My Custom List'); //To view all list types, view the SP.ListTemplateType enumeration on a SharePoint Website listCreationInfo.set_templateType(SP.ListTemplateType.genericList); var myList = curWeb.get_lists().add(listCreationInfo); ctx.load(myList); ctx.executeQueryAsync( function(){ alert('List created: ' + myList.get_id().toString()); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var myList = curWeb.get_lists().getByTitle('My Custom List'); myList.set_title("My Updated Custom List"); myList.update(); ctx.load(myList); ctx.executeQueryAsync( function(){ alert('List name updated!'); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var myList = curWeb.get_lists().getByTitle('My Custom List'); myList.deleteObject(); ctx.executeQueryAsync( function(){ alert('List deleted!'); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
Web Scope
//Often helpful to use '_spPageContextInfo.webTitle' OR web variable and use get_title() here for groups prefixed with web title var groupName = "Approvers" //Groups are usually inherited, for this example we grab the root web using the OOTB spPageContextInfo helper var ctx = new SP.ClientContext(_spPageContextInfo.siteServerRelativeUrl); var siteColWeb = ctx.get_web(); //Get groups, then query for specific group by name var collGroup = siteColWeb.get_siteGroups(); //Use the helper var oGroup = collGroup.getByName(groupName); var collUser = oGroup.get_users(); ctx.load(collUser); ctx.executeQueryAsync( function(){ console.log("Query success"); var userInfo = ''; var userEnumerator = collUser.getEnumerator(); while (userEnumerator.moveNext()) { var oUser = userEnumerator.get_current(); userInfo += '\nUser: ' + oUser.get_title() + '\nID: ' + oUser.get_id() + '\nEmail: ' + oUser.get_email() + '\nLogin Name: ' + oUser.get_loginName() + "<br/></br/>"; } alert("Users in '" + groupName +"' group: " + userInfo); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); //In this example we check to see if user can delete list items on the current web. //Output SP.PermissionKind for all possible permissions. Not all pertain to Web scope! var basePerm = new SP.BasePermissions(); basePerm.set(SP.PermissionKind.deleteListItems); var result = curWeb.doesUserHavePermissions(basePerm); ctx.executeQueryAsync( function(){ alert(result.get_value() ? "Has permissions" : "Does not have permissions") }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var propBag = curWeb.get_allProperties(); propBag.set_item("MyProp", "12345"); curWeb.update(); ctx.executeQueryAsync( function(){ alert('Property Bag Value Added!'); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var propBag = curWeb.get_allProperties(); ctx.load(propBag); ctx.executeQueryAsync( function(){ alert('Property Bag Key "MyProp" is set to "' + propBag.get_item("MyProp") + '"!'); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
var ctx = new SP.ClientContext.get_current(); var curWeb = ctx.get_web(); var propBag = curWeb.get_allProperties(); //setting to null will completely remove key/value from property bag propBag.set_item("MyProp", null); curWeb.update(); ctx.executeQueryAsync( function(){ alert('Property Bag Value "MyProp" removed!'); }, function(sender, args){ alert('Error: ' + args.get_message()); } );
Users
//This is the user to look up. Note that it must be prefixed with the auth and membership type. //Typically the prefix will always be i:0#.f|membership| var targetUser = "i:0#.f|membership|admin@YOURTENANT.onmicrosoft.com"; //Can look in Central Admin/SPO Admin area to confirm OR use commands similar to: //yourctx.get_web().get_currentUser().get_loginName() <-- use to view full current user login name //Global variable var userProfileProperties; // Ensure that the SP.UserProfiles.js file is loaded before the custom code runs. SP.SOD.executeFunc('SP.js', 'SP.ClientContext', function() { // Make sure PeopleManager is available SP.SOD.executeFunc('userprofile', 'SP.UserProfiles.PeopleManager', function() { getUserProperties(); }); }); function getUserProperties() { var clientContext = new SP.ClientContext.get_current(); var peopleManager = new SP.UserProfiles.PeopleManager(clientContext); //Properties from user profiles (These are CASE SENSITIVE) var profilePropertyNames = ["PreferredName", "Department"]; var userProfilePropertiesForUser = new SP.UserProfiles.UserProfilePropertiesForUser( clientContext, targetUser, profilePropertyNames); userProfileProperties = peopleManager.getUserProfilePropertiesFor(userProfilePropertiesForUser); clientContext.load(userProfilePropertiesForUser); clientContext.executeQueryAsync(onRequestSuccess, onRequestFail); } // This function runs if the executeQueryAsync call succeeds. function onRequestSuccess() { var messageText = "\"PreferredName\" property is " + userProfileProperties[0]; messageText += "<br />\"Department\" property is " + userProfileProperties[1]; alert(JSON.stringify(userProfileProperties)); } // This function runs if the executeQueryAsync call fails. function onRequestFail(sender, args) { alert(args.get_message()); }
Content Types
var ctx = new SP.ClientContext.get_current(); var web = ctx.get_web(); var cts = web.get_contentTypes(); ctx.load(cts); ctx.executeQueryAsync(onRequestSuccess, onRequestFail); // This function runs if the executeQueryAsync call succeeds. function onRequestSuccess() { var enumerator = cts.getEnumerator(); while (enumerator.moveNext()) { var curCt = enumerator.get_current(); console.log("CTID: " + curCt.get_id() + " | " + curCt.get_name()); } } // This function runs if the executeQueryAsync call fails. function onRequestFail(sender, args) { alert(args.get_message()); }
2 Comments
This is awesome. I am beginning to learn JSOM and I find this information very helpful.
Thanks!
HI when using the add listitem code I am getting
Record save failed error: Field or property “Title” does not exist.
when it obviously does. its the same for any field I try in the list Do you have any ideas why please?
Leave a Reply