Friday, November 13, 2015

Dynamic filtering of the Related Items list on a SharePoint form

Quite frequently our customers ask us how they can dynamically filter their related items lists based on a value entered into a field on a form created in Forms Designer. In this post I will describe how you can do that with a lookup, a drop-down choice and a people picker field. Although I will use these three field types, just about any field type will do for the job.

The steps for implementing this functionality are pretty straight-forward:

  1. Set your related items controls render mode to Client (see screenshot below).
  2. Add a CSS class name to it (see screenshot below). In following samples I will use the “related-issues” class name, if you use something different then replace “related issues” in the code with your class name.
  3. Add the appropriate code to the JS-editor. See code samples below.
Related Items in the client rendering mode

Lookup field

Say we have an issue form with a lookup to a department list and a related items list of other issues. These related issues need to be dynamically filtered based on the value in the Department field. The form will look something like this:

Filtering the related items by a lookup field

When we change the department, the list is refreshed straight away:

Filtering the related items by a lookup field

So, how do we achieve this?

After you have followed through the steps described in the previous section paste the following code into the JavaScript editor of your form:

//first filter on page load
setHash();

//and attach an on-change handler that will call the filtering function wherever the value of the field changes
fd.field('Department').change(setHash);

//this is the actual function that filters the list
function setHash(){
 //get value
 var value =  fd.field('Department').control('getSelectedText');
 if (value == "(None)") {
  value = "";
 }

 value =  encodeURIComponent(escape(value)).replace(/\-/g, "%252D");

 //set the URL’s hash value. An explanation on this is at the end of the article.
 window.location.hash = "InplviewHash" + $(".related-issues [webpartid]").attr("webpartid") + '=FilterField=Department-FilterValue=' + value;
}

In this code you will need to replace “Department” with the Internal Name (or Internal Names) of the field you’d like to filter:

  • Where it says fd.field('Department'), Department is the Internal Name of the lookup field that we get our value from.
  • Where it says FilterField=Department Department is the Internal Name of the field in the target list that is being sorted.

In our case the two Internal Names are the same, but they don’t have to be.

And this is it, now our related issues are auto filtered based on the selected Department whenever user changes the value of the Department field.

Dropdown choice field

Here we will do exactly the same thing, but using the Issue Status field, which is a single-value drop-down choice field.

Filtering the related items by a drop-down field

This is the code:

setHash();

fd.field('Issue_x0020_Status').change(setHash);

function setHash(){
 var value =  encodeURIComponent(escape(fd.field('Issue_x0020_Status').value())).replace(/\-/g, "%252D");
 window.location.hash = "InplviewHash" + $(".related-issues [webpartid]").attr("webpartid") + '=FilterField=Issue_x0020_Status-FilterValue=' + value;
}

Here you will need to replace “Issue_x0020_Status” with the appropriate Internal Name(s), for details on this see the Lookup field section above.

Single-value Client-mode people picker field

In this case we want to filter our issues based on the Assigned To field:

Filtering the related items by a user field

This is our code:

setHash();

fd.field('Assigned_x0020_To').change(setHash);

function setHash(){
 var value = "";

 //if the people picker field really has a value, get it
   if (fd.field('Assigned_x0020_To').value() && fd.field('Assigned_x0020_To').value()[0] && fd.field('Assigned_x0020_To').value()[0].DisplayText){
  var value =  encodeURIComponent(escape(fd.field('Assigned_x0020_To').value()[0].DisplayText)).replace(/\-/g, "%252D");
 }

 window.location.hash = "InplviewHash" + $(".related-issues [webpartid]").attr("webpartid") + '=FilterField=Assigned_x0020_To-FilterValue=' + value;
}

As with the previous field types you’ll need to swap “Assigned_x0020_To” for the appropriate Internal Name value(s), see the Lookup section for more detail.

Other fields

You can utilize this feature with pretty much any type of field, but you need to know how to retrieve the value of the field. For a list of field types and corresponding ways to retrieve their values check this page: http://formsdesigner.blogspot.com/2013/04/getting-and-setting-sharepoint-form.html.

Explanation

To make this work we are utilizing the SharePoint URL hash feature that is used with SharePoint 2013 views in the client-side rendering mode.

Have a look at this sample URL:
https://mywebsite.com/Lists/Issue/fd_Item_EditForm.aspx?ID=20#InplviewHash3f6a312c-cd80-4e64-be27-075b976ced40=-FilterField1=Parent-FilterValue1=20-FilterField2=Issue_x0020_Status-FilterValue2=In Progress

What our code samples do is set the “InplViewHash” part of the URL together with its FilterField and FilterValue values, which is what tells the related items control to sort the list. Simple as that.

9 comments:

  1. Hi Dmitry, thanks a lot for the post, the solution works perfectly when i only have one related list, however i can't get it to work when i have multiple related lists, for example i have a tab called "Related" and i placed 3 different related lists in an accordion control inside the related tab. how do i get this to work for them all? I tried to open the link in your post: https://mywebsite.com/Lists/Issue/fd_Item_EditForm.aspx?ID=20#InplviewHash3f6a312c-cd80-4e64-be27-075b976ced40=-FilterField1=Parent-FilterValue1=20-FilterField2=Issue_x0020_Status-FilterValue2=In Progress
    however it's not working. Thanks in advance for your response.

    ReplyDelete
    Replies
    1. Hi Mohamed,
      The solution should work for multiple Related Items as well. You only need to assign different CSS-classes to those controls and use them in JavaScript as appropriate.

      Delete
    2. Hi Dmitry,
      Thanks a lot for your response, here's the code that i'm using, i only added a couple of lines to set the URL's hash with a different CSS class, however it's not working yet.
      //first filter on page load
      setHash();
       
      //and attach an on-change handler that will call the filtering function wherever the value of the field changes
      fd.field('Project').change(setHash);
       
      //this is the actual function that filters the list
      function setHash(){
       //get value
       var value =  fd.field('Project').control('getSelectedText');
       if (value == "(None)") {
        value = "";
       }
       
       value =  encodeURIComponent(escape(value)).replace(/\-/g, "%252D");
       
       //set the URL’s hash value. An explanation on this is at the end of the article.
       window.location.hash = "InplviewHash" + $(".rel-tasks [webpartid]").attr("webpartid") + '=FilterField=Project-FilterValue=' + value;
      window.location.hash = "InplviewHash" + $(".rel-proj [webpartid]").attr("webpartid") + '=FilterField=Title-FilterValue=' + value;
      window.location.hash = "InplviewHash" + $(".rel-opp [webpartid]").attr("webpartid") + '=FilterField=Project-FilterValue=' + value;
      }

      Delete
    3. Hi,
      You need to concatenate the hash instead of replacing it in the end of your script:

      var hash = "InplviewHash" + $(".rel-tasks [webpartid]").attr("webpartid") + '=FilterField=Project-FilterValue=' + value;
      hash += "#InplviewHash" + $(".rel-proj [webpartid]").attr("webpartid") + '=FilterField=Title-FilterValue=' + value;
      hash += "#InplviewHash" + $(".rel-opp [webpartid]").attr("webpartid") + '=FilterField=Project-FilterValue=' + value;
      window.location.hash = hash;

      Delete
    4. Thanks a lot, you're the man :) works like a charm. Merry Christmas and happy new year Dmitry.

      Delete
  2. Does the sample code for lookups require the cross-site lookup application?

    Is there a way to make these work on a new form rather than an edit form?

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hi Dmitry, is it possible if we filter the related items based on multiple values e.g. Issue Status, Ticket No etc ? Thanks in advance.

    ReplyDelete
    Replies
    1. Morning Luke

      Did you get a solution for this?

      Delete