Introduction

This article will explain step by step guidelines to implement lookup columns, multi-value lookup columns and how to filter the values using REST API & CAML query.
To know about the basics of Lookup Columns in SharePoint using CAML Queries, use the below reference links:

Cascading drop down in SharePoint using REST API

Cascading drop down or filtered lookup columns in SharePoint is one of the most used functionalities in most of the projects for various business needs.

In one of my old articles, I have explained about creating cascading or filtered lookup columns using JQuery & SPServices in MOSS 2007 version of SharePoint. 

Cascading drop down (or) Filtered Values in Lookup Columns in SharePoint

This solution has limitations such as this will work only in List Forms and it may not work after certain limit of values in the drop down.

In this article, lets learn to implement Cascading or Filtered Lookup Columns in latest versions of SharePoint using REST API (applicable to SharePoint 2013, Office 365 – SharePoint Online, SharePoint 2016). REST API uses OData (Open Data Protocol) services to read/write/update data in SharePoint.

I have created 2 lists with the following information as shown below:

  • Drinks 
  • Drinks Type (Drink column is a lookup column to display Title from Drinks List)    

Now, create a list to test the cascading or filtered lookup functionality. I have created a list and named it as “Drinks Menu”
Please note, the Drinks and Drink Type columns are created as Choice type and all the values from Drinks and Drink Type are added as choices in these fields. This is implemented in this way so that we can avoid the issue surfaces when we have large number of options in Lookup Column. 

Also, if you add a new value to parent lists (Drink or Drink Type lists in this scenario), add the values as choice in the cascading lookup value implementation list ( Drink Menu list in this scenario).

Now, click on the new item which will open the “NewForm.aspx” -> Edit the page -> Add a Web Part -> Insert -> Categories -> Media and Content -> Script Editor -> Click Add to add it.

In the Script Editor, click Edit Snippet and add the CascadingDropdown.js (download from the below attachment). I have referred “JQuery.1.12.0.min.js” in the code which is also available for download. Make sure JQuery is referenced properly in your code else, the script won’t work.

Following are the scenarios I have covered in this example:

When “Drinks” drop down is not selected or changed to empty, then “Drink Type” & “Price” fields should be disabled and empty

When “Drinks” is selected, “Drink Type” should cascade (filter the values) and show the types based upon selection
When “Drink Type” is selected, the “Price” should automatically populate in the Price field
The data saved to the list will look as shown below:
JS code for cascading the lookup values (Drinks -> Drink Type) is shown below:
//Function to filter the values of Drink Types
function loadDrinkTypes(selectedDrink) {
    var drinkTypeListName = "Drink Type";
    var drinkTypeListURL = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + drinkTypeListName + "')/items?$select=Title,Drink/Title,Drink/Id&$expand=Drink&$filter=Drink/Title eq '" + selectedDrink + "'";
    getReqData(drinkTypeListURL, function (data) {
        var items = data.d.results;
        if (items.length > 0) {
            var optionsAsString = '<option value=""></option>';
            for (var i = 0; i < items.length; i++) {
                optionsAsString += "<option value='" + items[i].Title + "'>" + items[i].Title + "</option>";
            }
            $('select[title="Drink Type"]').html(optionsAsString);
        }
    },
        function (data) {
            //alert("Some error occurred in getting Drink Types");
        });
}
 
//JQuery AJAX to access REST API JSON data
function getReqData(reqUrl, success, failure) {
    $.ajax({
        url: reqUrl,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: function (data) {
            success(data);
        },
        error: function (data) {
            failure(data);
        }
    });
}

JS code for setting the Price value automatically on Drink Type selection is shown below:

//Function set the Drink Price
function setDrinkPrice(drinks, drinkType) {
    var drinkTypeListName = "Drink Type";
    var drinkTypeListURL = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + drinkTypeListName + "')/items?$select=Price&$filter=(Drink/Title eq '" + drinks + "') and (Title eq '" + drinkType + "')";
    getReqData(drinkTypeListURL, function (data) {
        var items = data.d.results;
        if (items.length > 0) {
            var price = "";
            for (var i = 0; i < items.length; i++) {
               $("input[title='Price']").val(items[i].Price);
            }
        }
    },
        function (data) {
            //alert("Some error occurred in getting price");
        });
}



Please download the full code to view how each method are called in document.ready(). Download the JS files, List Templates from this link for the complete solution.

Note:

1. The above code is tested in SharePoint Online (all the lists are in Classic Mode and not Modern List views in SP Online).

2. It should work in SharePoint 2013 and 2016 versions as well.

Multi value Lookup Columns in SharePoint

Now, let's learn about creating multi-value lookup columns in SharePoint and also to filter the values upon selecting the multi-values.

Let's go ahead and create two source lists for this demo:

1. States 

2. Cities (State is a lookup column from States list)

3. The third list will be used to implement the Multi-value lookup column and also we are going to implement filtering multi-value lookup columns in this article. I have created a list named "Multi value lookup demo" which has State and City as lookup value from the first two lists created. Make sure, you select Allow multiple values options as shown below:

The new item form without filtering looks as shown below:
Following are the functionalities to be implemented & issues/challenges needs to be considered while implementing filtering multi-value lookup columns in SharePoint:

1. An option can be double clicked to select or clicked Add button to select a value

2. An option can be double clicked to deselect or clicked Remove button to deselect a value

3. More than one option can be selected and can be bulk added to the selected values

4. The JQuery implemented should satisfy the above conditions while filtering

5. When State is selected, the values of Cities should get filtered. In the same way, when a value from the deselected then the values from Cities should be removed

Add a Script Editor web part in New item form and added JQuery as reference. Also, added the JS code which will implement the filtering functionality.

$(document).ready(function () {
    //Call multi-value lookup function on selecting State
    $("select[title='State possible values']").dblclick(function () {
        multiValueLookup();
    });
    //Call multi-value lookup function on removing State
    $("select[title='State selected values']").dblclick(function () {
        multiValueLookup();
    });
    //Call multi-value lookup function on clicking Add - State
    $("input[value='Add >'][id^='State_']").click(function (){
        multiValueLookup();
    });
    //Call multi-value lookup function on clicking Remove - State
    $("input[value='< Remove'][id^='State_']").click(function () {
        multiValueLookup();
    });
});
function multiValueLookup() {
    var items = "";
    var citiesListName = "Cities";
    $("select[title='City possible values'] option").remove();
    $("select[title='State selected values'] option").each(function (i) {
        var clientContext = new SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle(citiesListName);
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><Query><OrderBy><FieldRef Name='Title' /></OrderBy><Where><Eq><FieldRef Name='State' LookupId='TRUE'/><Value Type='Lookup'>" + $(this).val() + "</Value></Eq></Where></Query></View>");
        var items = oList.getItems(camlQuery);
        clientContext.load(items);
        clientContext.executeQueryAsync(success, failure);
        function success() {
            var pn2 = "";
            var pn1 = "";
            var ListEnumerator = items.getEnumerator();
            while (ListEnumerator.moveNext()) {
                var currentItem = ListEnumerator.get_current();
                if (currentItem.get_item('Title') != null) {
                    var pn1 = currentItem.get_item('Title');
                    if (pn2 != pn1) {
                        items = "<option value='" + currentItem.get_item('ID') + "' title='" + pn1 + "'>" + pn1 + "</option>";
                        $("select[title='City possible values']").append(items);
                        pn2 = pn1;
                    }
                }
            }
        }
        function failure(sender, args) {
            // alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
        }
    });
}


If you want to implement the same functionality in Edit item form, following the same steps just mentioned above.
When an value is selected
When an value is deselected
The final value stored in the list is shown below:
Cool isn't it? Very simple as well. 

This is tested in SharePoint Online and I am sure it should work for SharePoint 2013, 2016 & 2010 as well.

Download, list templates, JS code using CAML, JS code using REST API from here.