2010, 2013, 2016, Development Blog, jQuery, Office 365, SharePoint
Clean CSOM JavaScript structure to access SharePoint list data
The code examples below work on SharePoint 2010, 2013 and 2016.
The problem:
You want to create clean, maintainable CSOM for SharePoint and ensure that you:
- don’t override any SharePoint default variables
- don’t override any third party JavaScript frameworks that are running on your site
The answer:
Encapsulate your entire JavaScript library in a variable, which will handle all your functions and global variables. This is the structure I follow routinely, and with even the most complicated JavaScript calls, this is still very maintainable.
I hope the code samples below help you. Please also look at SharePoint JavaScript CSOM – currentItem.get_item(columnName) – how do I get at the property options and values? to see all the out-of-box options for listItem.get_items(KEY).
The basic structure:
var yourUniqueVar = { "g": { }, "init": function() { // Load additional JS libraries required to execute your code }, "mainFunction": function() { // All JS libraries and other inits are now loaded // Prep data objects, and toss them at the client context }, "success": function(sender, args) { // Iterate through data, create data object and add it to your globals }, "fail": function(sender, args) { // Handle errors }, "renderHTML": function() { // Use data object created in "success" to render HTML }, "finalise": function() { // Wrap up anything else that needs to happen } }
A code example:
This is the JavaScript necessary for pulling the data. (FYI – this relies on jQuery, so load it via CDN if necessary).
var stephy = { /* Define global variables here */ "g": { /* Relative Site URL */ "siteUrl": "/sites/MySiteName", /* Library Display Name - we'll use the Pages library for this example */ "libraryName": "Pages", /* Library object to house data */ "library": null, /* Array to house list item objects */ "items": [], /* Web object to put the web's information into */ "web": null }, /* Init function */ "init": function() { // Add a loader (to give your users a pacifier) $('#stephyDiv').addClass("stephy-loading"); // Load necessary libraries SP.SOD.executeFunc('sp.js', 'SP.ClientContext', stephy.loadData); }, /* Prep the list loading function */ "loadData": function() { // Create all items CAML query (gets all items in a list) var camlQuery = new SP.CamlQuery.createAllItemsQuery(); // Point CAML at the library camlQuery.set_folderServerRelativeUrl(stephy.g.libraryName); // Get the clientContext, which will handle the request with the current user's permissions var clientContext = new SP.ClientContext(stephy.g.siteUrl); // Get the web object stephy.g.web = clientContext.get_web(); // This puts the web object in the clientConext (to get the data) and is also globally available so you can call it later clientContext.load(stephy.g.web); // Set a local variable to handle the library request var library = stephy.g.web.get_lists().getByTitle(stephy.g.libraryName); // Now add it to a global for access in the success object stephy.g.library = library.getItems(camlQuery); // This puts the library in the clientConext (to get the data) and is globally available so you can call it later clientContext.load(stephy.g.library); /* You can repeat this process and throw multiple list requests at the same clientContext so * it is executed in one AJAX request - just use different library objects (so each list is accessible in your success function) * CAUTION - if you do throw multiple lists / objects into the same clientContext request, one of them failing results in the entire request failing */ // Execute Query - this throws it at SharePoint, and once complete, will run your getAndPopulateDataSuccess function, or fail if there's a problem clientContext.executeQueryAsync( Function.createDelegate(this, stephy.getAndPopulateDataSuccess), Function.createDelegate(this, stephy.onQueryFailed) ); }, /* After clientContext handles AJAX request, this runs on success */ "getAndPopulateDataSuccess": function(sender, args) { // Get site information from the (now populated) global variable stephy.g.web var message = "\n Title: " + stephy.g.web.get_title(); message += "ID: " + stephy.g.web.get_id() + ""; message += "Language: " + stephy.g.web.get_language() + ""; message += "UI Version: " + stephy.g.web.get_uiVersion() + ""; message += "Description: " + stephy.g.web.get_description() + ""; message += "Created: " + stephy.g.web.get_created(); // Put it on the page so you can view it $('#stephyWebDiv').html(message); // Get library data from the (now populated) global variable stephy.g.library var listItemEnumerator = stephy.g.library.getEnumerator(); while (listItemEnumerator.moveNext()) { // Get the current list item var listItem = listItemEnumerator.get_current(); // Now load whatever other data you want to load, ie: var title = listItem.get_item('Title'); var url = listItem.get_item("FileRef"); /* I prefer to push all the objects into an array first and then iterate * over the data in the next function to create clear separation between data and layout */ stephy.g.items.push({ "title": title, "url": url }); } stephy.renderHTML(); }, /* After clientContext handles AJAX request, this runs on failure with an error message */ "onQueryFailed": function(sender, args) { alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace()); }, "renderHTML": function() { // Loop through the data and populate the HTML variable var html = ""; $.each(stephy.g.items, function(index, value) { html += ''; html += ''; }); // Remove the loader $('#stephyDiv').removeClass('stephy-loading'); // Add the HTML to your container $('#stephyDiv').html(html); // Run any additional init functions here (ie. if you’re relying on another framework to create a carousel or something) } } // On page load, run the init function $(document).ready(function() { stephy.init(); });' + value.title + ''; html += '' + value.url + ''; html += '
And here is the HTML (and some basic styling) necessary to make this work.
No list information yet.No web information yet.
About Author
Comments are closed