Skip Ribbon Commands
Skip to main content


> Posts > Creating a Parent/Child List Relationship with a Document Library
March 29
Creating a Parent/Child List Relationship with a Document Library

To this day, my most popular blog posts continue to be my posts on how to set up a parent/child list relationship in SharePoint. These blog posts show you how to automatically set the ID of a Lookup field for a “child” list for different versions of SharePoint using various methods:

As helpful as many have found these solutions, they only worked for lists and not for document libraries. The reason for this is that we are using query string variables to pass the ID of the parent list to the child new form. However, when you add a document to a document library there are two forms. The first form is a dialog for uploading your file, and the second form is the page used for entering all the various properties for the file including the lookup field for the parent.  When using the query string method from the previous posts, the ID for the parent list item is passed to the upload dialog, NOT the properties page.

So, the problem is that we need to persist the parent item’s ID until the properties form is displayed for our newly uploaded file and then set the form field accordingly. I don’t really want to get into customizing the upload dialog to pass along the query string variable and adding script to the Master Page for this one purpose would be woeful.  So, what to do?

C is for Cookie

Sorry, I couldn’t think of any other cookie analogy but by taking advantage of cookies we can set a cookie with our parent list item ID and our properties page will be able to read it.

Why I like the cookie option

Using a cookie ends up being a fairly simple solution and even adds some additional benefits:

  • By setting a cookie with your Parent List ID you can easily have multiple child lists that can all easily access the cookie.
  • A cookie will work for both lists and document libraries.
  • You can store other field values in additional cookies and pass those to your forms as well.

Why I DON’T like the cookie

So, as cool as this cookie idea sounds and as many benefits as I get, I’m still not THRILLED about using a cookie for a couple of reasons:

  • When you create a cookie, it remains accessible to your pages until it expires. This has benefits, but it also CAN create issues. You could conceivably have a page use a cookie that you didn’t mean for it to use if you aren’t careful.
  • Once a developer (especially inexperienced ones) latch onto a device such as cookies they can go a bit crazy with it and start using it all over the place. I don’t like the thought of someone creating a ton of cookies that they don’t expire and then asking me to debug their form because for SOME reason it ALWAYS sets a form field to the value “42”.
  • On that same note, if a developer creates a generic name for a cookie and some other developer on that site decides to use cookies too and uses the same generic name, you’re going to be possibly overwriting each others values. You’re code will work fine on your machine… but have fun debugging that one. Make sure to use a unique cookie name.
  • How do I handle expiring a cooking? Expire it right after I’ve used it? Let it expire in 5 minutes? a day? well… “it depends”. Which means you SHOULD give them some thought when use them and not just blindly make a decision. So, it CAN add some complexity. For this blog I chose to keep it simple and let my cookies expire after 5 minutes.

The Solution

As I said, the solution ends up being actually fairly simple, and you can view the video below to see step-by-step how I did it. In the video I’ll be using the cookie for both a child list and a child document library. With just a couple of scripts we can be up and running quite quickly.  If you don’t want to watch the video, but want to know what I did, here are the steps to take:

Create the infrastructure

Create your lists and libraries. Create lookup fields to your parent list in your child lists and libraries. For this blog, I’ll stick with my conventions from my previous posts on the subject.  I will have a Parent list “Issue”, a child list “Time”, and a new child library “IssueDocuments”. Each child list has a lookup field to the “Issue” list with the name “Issue” and I’m looking up on the “Title” field.

Edit the default display form for your parent list.


Add list view web parts for your children forms onto the page.


Create web part connections from your parent list to your children list filtering the children list by the parent list ID and the child list/library lookup field.



After you have you child list views added and the web part connection set up, go ahead and manually create a couple of entries in your children lists/libraries selecting a valid parent from the lookup field. You will see that only the children for the parent list item will show in the list views on the Issue display form. Now to set it up so you don’t have to manually set the lookup field value for the parent.

Add a script to the default display form of the parent list

Edit the default display form of the parent list again, add a content editor web part and link it to the following script which I’ll be placing in my Site Assets library. In this script I’m creating a cookie for the parent list ID that exists in the query string of my parent display form. I’m giving the cookie the name “IssueID” and having it expire in 5 minutes.

<script type="text/javascript">
    //get the ID for the Issue from the Query String
    var issueID = getParameterByName("ID");

    //create a cookie with the name "IssueID"
    // The following function should really be put into a utility library
    // with all of your commonly called functions
    // no, I didn't write this function from scratch, I found it at
    function getParameterByName(name)
      name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
      var regexS = "[\\?&]" + name + "=([^&#]*)";
      var regex = new RegExp(regexS);
      var results = regex.exec(window.location.href);
      if(results == null)
        return "";
        return decodeURIComponent(results[1].replace(/\+/g, " "));
    function createCookie(name, value) {
       var date = new Date();
       //make the cookie expire in 5 minutes
       var expires = "; expires="+date.toGMTString();
       document.cookie = name+"="+value+expires+"; path=/";

If you’ve followed my previous blogs on the subject, you’ll remember that we had to previously modify the link to the “Add New Item” on the child list view to make it pass the IssueID to the child list form in the query string. Well, since we are using cookies, we don’t need to modify the default “Add new item” or “Add new document” links at all. This also means you can add several child list views without having to modify the above script at all. That’s a nice side benefit of using cookies.

So, now when you load the the display form of your parent list item, a cookie is being set called “IssueID” that contains the ID of that parent list item.

Add a script to our children forms

At this point, all we have to do to make this all work together is add a script to the New Item Form of our child Lists and the Edit Forms of our child Document Libraries.

<script  type="text/javascript" src=""></script>

<script type="text/javascript">
     jQuery(document).ready(function($) {
        var issueID = getCookie("IssueID");
        if (issueID != undefined)
            SetLookup("Issue",issueID );
    function getCookie(name) {
        var cookieArray = document.cookie.split(";");
        for (index in cookieArray)
            var keyValuePair = cookieArray[index].split("=");
            var key = keyValuePair[0];
            key  = key.replace(/^\s+|\s+$/g, "");
            if (key == name)
                var value = keyValuePair[1];
                return value;

    //Sets the value of a lookup field whether it is an input or select field. 
    function SetLookup( fieldTitle, lookupVal)
        //Set default value for lookups with less that 20 items
        if ( $("select[title='" +fieldTitle+ "']").html() != null)
            var element = $("select[title='"+ fieldTitle +"']");
            //disable field to stop pesky users from changing it
            $(element).find('option:not(:selected)').attr('disabled', true);
            choices = $("input[title='" +fieldTitle +"']").attr("choices");
            hiddenInput = $("input[title='" +fieldTitle +"']").attr("optHid");
            $("input[id='" +hiddenInput +"']").attr("value",lookupVal)
            choiceArray = choices.split("|");
            for (index = 1; index < choiceArray.length; index = index + 2)
                if (choiceArray[index] == lookupVal){
                    var element = $("input[title='" +fieldTitle +"']");
                    $(element).val(choiceArray[index - 1]);    
                    //disable field to stop pesky users from changing it
                    //hide the button that is used for the dropdown list


In this script, the script simply looked for a cookie called “IssueID” and if it found the cookie, it used the value of the cookie and set the form field “Issue” to that value. It then disabled the “Issue” field on the form to stop those pesky users from changing it to something else. If you are passing multiple fields in multiple cookies you would just use the same logic to set the various form fields for each cookie. If you need to know how to set various form fields in a SharePoint form, you can reference my previous blog post on the subject:

A Dummies Guide to SharePoint and jQuery–Getting & Setting SharePoint Form Fields

The last thing I’ll point out about this script is that it takes into account the 20 item lookup field “feature” in SharePoint 2007 and 2010:

Setting SharePoint Lookup Lists w/ jQuery (+/- 20 items)

This does not seem to be an issue in SharePoint 2013 and a lookup field is always a select (unless something has changed since I last tried), so if you are using SharePoint 2013 you don’t need the portion of the script that looks for the “Issue” field as an input.

That’s it! You’re done! Now when you open up the display form for your parent list and click on the “add new…” link for any of your child lists (that you applied the above script to on their respective forms), the parent lookup field value will automatically be set and the lookup field will be disabled.

The Video

So, you don’t like reading and you just want to watch me do it all? Okay, let’s see if I can do it all in one take without screwing up:



So, this solution will work on SharePoint 2007, 2010, 2013 and in Office 365. That’s pretty cool. Will I start using cookies more often? I’ll continue to use them judiciously and when it makes sense. I’m not enamored by the thought of having this data floating around that I no longer need and getting bit by it because some developer didn’t create a unique cookie name and it messes up some other page.

I see this being an extremely useful tool to use though, but please learn all your tool options and use the right one for the right project.

Thanks again for taking the time to read my ramblings. Yes, there’s 100 ways to skin a cat, so if you have a better/easier solution please feel free to share with the class!


Cookies Can Be Bad for Your Teeth

I think a cookie is a great way to do this, but if you'd like to do it by passing values on the query string instead, I came up with a way in this old post:

 on 3/29/2013 6:11 PM

Very nice post

Cool! I had done something as well though not sure if it applies.
Clicking on view properties of a document, show related items though OOB but clicking on New Task i.e would take the query string value of the document since we are in view properties and set the lookup value of the task to this document.
 on 3/30/2013 5:04 PM

Few fixes

I had problems when the SetLookup() function would fire before the New item window had opened (I use Dialogs)

Changing the (document).ready to (window).load in the child script fixed this for me

Also I reduced the cookie expiration to 1 minute, because 5 minutes is enough time for someone to go back to the main menu, open up the child item directly to create a new item and the cookie is still alive, preventing the selection.
 on 1/15/2014 8:13 PM

Can I enter both parent and children at same time?

Is it possible to "Add new item" in the parent list, enter the parent info, and at the same time then go ahead and enter child items?

For data entry purposes having to enter and save a parent item before re-opening the parent to add the children seems not very efficient.
 on 1/22/2014 6:11 PM

Parent and Child at the same time

You cannot "out of the box" enter both a parent and child at the same time. There are several "hacks" you could do to accomplish though including:

1) Don't use SharePoint's save button and implement your own save function using CSOM or SPServices to create parent and child entry

2) even more of a hack would be to set all the values of the child form in cookies and have the save direct you to the child form which you fill out and trigger the save click with script.. major hack but would work in a pinch.

3) Create an SPD Workflow for parent item and initially store child fields in parent list. in the workflow, create the child entry.

like I said, they are all pretty much hacks if you are trying to use SharePoint's default new item forms. 
EMS\markrackleyNo presence information on 1/22/2014 8:18 PM

SharePoint Architect, Developer, Blogger, Speaker, Author, and general pain in the butt.
Thoughts, views, and opinions expressed in this blog are solely my own.
Remember, the Impossible just takes longer.

 Blogs you should be reading