SharePoint Developer Team Blog
Brought to you by Microsoft teams working on SharePoint developer content, Visual Studio tools, and of course the platform itself!
The SharePoint team did a great job in ensuring that there is significant similarity in the server and client object models with regards to their syntax and behavior. If you have developed in SharePoint by using the server object model, you likely noticed that most operations in the client object model are similar to the operations you perform when using the server object model.
The following discussion demonstrates some common list operations that can be performed using JSOM. You may want to display the monthly sales of an employee and track them against the annual target sales. The sales target is defined based on their role in the organization. You want to provide a Sales Target View where management can view the current Sales achieved by an employee and compare it against its Sales Target. You select an employee from a list that displays the sales achieved by the employee. Finally, you want to show whether the employee is an "Achieved", "Lagging Behind" or "Super Performer" by comparing the total of the sales achieved with the configured Sales Target for the employee role.
For this purpose, a simple Web Part and some custom lists has been created that allows the users to select an employee and then display their sales information. First, create a custom list called Employee which stores general information about the employee (no AD sync for now). The following diagram shows how the employee list looks.
The sales target is based on a role and stored in another list named SalesTarget.
To track the monthly sales for each employee, another list named Sales is created which stores details about each Sale associated with the employee.
The UI looks similar to the following.
To begin, you want to display all the employees in the Employee list so that management can choose which employee data to view. For this purpose, you add a button named GetEmployees and bind the Click event of this button to call a Javascript method. The method leverages JSOM to populate a radio list with all employees in the organization. The following is a sample of the get_employees() method.
function get_Employees(control) {
try {
this.baseControl = control;
this.controlToLoad = control + "_chkEmployeeList";
var context = new SP.ClientContext.get_current();
// Load the web object
this.web = context.get_web();
//Get the list
var list = this.web.get_lists().getByTitle('Employee');
// Get all the items in the list
employees = list.getItems('');
// Load the web in the context and retrieve only selected columns to improve performance
context.load(this.employees, 'Include(ID,EmployeeName,Role)');
//Make a query call to execute the above statements
context.executeQueryAsync(Function.createDelegate(this, this.get_Employees_onSuccess), Function.createDelegate(this, this.get_Employees_onFailure));
}
catch (e)
{
alert("An error occurred while fetching data. Please contact your system administrator.");
To analyze what is happening in the get_Employees method, consider the following:
Load: This is also called as an In-Place load. This load variant should be used when you want to load objects and collection and maintain their state through multiple requests. Essentially, whatever object that you pass into the load method is populated and can be used as-is in subsequent requests.
LoadQuery: The LoadQuery variant returns a new instance or collection every time it is called. This is beneficial when you want to return an enumerator to the object which you want to maintain yourself.
Both the variant can take a parameter that defines which columns to return. For loading a singular object, you simple pass the names of the columns separated by commas as followings:
context.load(<object>,'<Field1>','<Field2>','<Field3>');
In case the object is a collection, you can still specify the columns to include in the load operation by using the following format 'Include(<Column1>, <Column2>,<Column3>, …)' format.
context.load(<objectCollection>,'Include(<Field1>,<Field2>,<Field3>');
Note that if you want to access the child properties of an object, you must load the object (by calling the ExecuteQueryAsync method) before you can access it; otherwise, you will generate an exception such as the following:
The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
JSOM only supports the asynchronous version of ExecuteQuery and so you need to provide two callback methods whenever you make a call to ExecuteQueryAsync; these methods specify the success and failure callback methods to call on the client when the request has been processed.
function get_Employees_onSuccess() {
// Get the collection
var employeeCollection = this.employees.getEnumerator();
// get the control
var chkBoxList = document.getElementById(this.controlToLoad);
// get the checkbox group
while (employeeCollection.moveNext()) {
var employee = employeeCollection.get_current();
addRowForEmployeeList(this.controlToLoad, employee.get_item('ID'), employee.get_item('EmployeeName'), employee.get_item('Role'));
function get_Employees_onFailure() {
JSOM supports properties and methods similar to the server object model to retrieve specific items. The following code snippet retrieves an object based on it ListItem ID.
function get_EmployeeById(employeeId) { try { var context = new SP.ClientContext.get_current(); this.web = context.get_web(); var list = this.web.get_lists().getByTitle('Employee'); this.employee = list.getItemById(employeeId); context.load(this.employee, 'EmployeeName', 'Role'); context.executeQueryAsync(Function.createDelegate(this, this.get_Employee_onSuccess), Function.createDelegate(this, this.get_Employee_onFailure)); } catch (e) {
alert("An error occurred while fetching data. Please contact your system administrator."); }
You can also use the SharePoint CAML query language to filter data when loading objects. The client object model provides a SP.CamlQuery type that is used to pass a CAML query when the object is loaded. Simply assign your CAML query string to the set_viewXml method of CamlQuery and pass it to the object that supports it (for example, getItems(CamlQuery).
In the following code, you use a CAML query to retrieve the sales data for an employee:
function get_EmployeeSales(employeeName) {
this.controlToLoad = this.baseControl + "_" + "tblEmployeeSales";
var list = this.web.get_lists().getByTitle('Sales');
// Get all items based on query
var query = '<View Scope=\'RecursiveAll\'>' +
'<Query>' +
'<Where>' +
'<Eq>' +
'<FieldRef Name=\'EmployeeName\' />' +
'<Value Type=\'LookUp\'>' + employeeName + '</Value>' +
'</Eq>' +
'</Where>' +
'</Query>' +
'</View>';
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml(query);
this.salesDetails = list.getItems(camlQuery);
context.load(this.salesDetails, 'Include(ID,EmployeeName,SalesAchieved,SaleDate,Customer,Title)');
context.executeQueryAsync(Function.createDelegate(this, this.get_EmployeeSales_onSuccess), Function.createDelegate(this, this.get_EmployeeSales_onFailure));
catch (e) {
alert("error occurred" + e.toString());
Property Getters and Setters in JSOM
If you look closely at the type signatures, you will notice that the JSOM properties are different in their naming conventions as compared to CSOM or the server object model. Basically, JSOM provides a getter and setter model for most properties of SharePoint objects. Any value that needs to be accessed can be obtained by using the get_<PropertyName> methods for the corresponding object; similarly any property assignments can be performed by using the set_<PropertyName> methods for the objects. You can find information about the various methods available in the SP namespace.
In this post, you saw the various ways to retrieve items from a SharePoint list. In the next post, you work on some data manipulation operations that you can perform on a list.