This project has moved and is read-only. For the latest updates, please go here.

Multiple Field Dependencies

Mar 23, 2016 at 10:02 PM
I have a sharepoint list with several dependent fields. Meaning that they are intially hidden and they get revealed depending on other selections. There are multiple branching paths they can take and the coding is getting complex. The part I am struggling with the most is if you change fields making other dependent fields change more than one tier down.

For example:
Dropdown Field A Yes/No
If Field A = Yes
Show Field B
Show Field C
End If

Dropdown Field B
If Field B = Yes
Show Field D
Show Field E
End If

Now if they change Field A to no, I can easily Hide Field B and Show Field C, but I am having difficulty now hiding Field D and E. I know it has something to do with .change not triggering when JavaScript creates the change, but I can figure out another alternative. I've created functions that try and cascade through each field but that causes it to be buggy. Does anyone have any advice for multiple branching options?
Mar 25, 2016 at 11:42 PM
Should be doable. I'm going on vacation but I'll set up a test when I get back.
Apr 1, 2016 at 12:18 AM
So I started looking at this and it turned into a pretty interesting problem. I think I went a bit overboard with the solution I came up with but I'll post it and get your feedback.

Assume you have the following Dropdown fields each with only Yes and No for values. When the value is Yes, the dependent fields are visible and when the value is No the dependent fields are hidden.
0) Do you want cake?
  1) Do you want ice cream with your cake?
    2) Do you want chocolate ice cream?
    2) Do you want vanilla ice cream?
  1) Do you want a donut?
It all started with the need to track the dependencies between fields in some way. I immediately thought of creating a big JSON object which would look like a tree but it soon became kinda unmanageable once you get a few levels deep. Instead I created a fluent API to make it easier and more readable:
var cakeTree = new SPUtilityTree('Do you want cake?');
// add two dependencies on 'Do you want cake?' with different values
cakeTree.whenField('Do you want cake?').hasValue('Yes')
.showFields(['Do you want ice cream with your cake?']);
cakeTree.whenField('Do you want cake?').hasValue('No')
.showFields(['Do you want a donut?']);
// add two dependencies on 'Do you want ice cream with your cake?' with same value
cakeTree.whenField('Do you want ice cream with your cake?').hasValue('Yes').showFields([
   'Do you want chocolate ice cream?',
   'Do you want vanilla ice cream?'
// done adding additional field dependencies
// build the tree which prints it out and initializes the form;
// dropdown fields are now hidden automatically based on the selection!
Behind the scenes, it builds a tree to track dependencies. This works pretty good because I can always iterate through the tree using recursion. I quickly ran into a couple problems though.

First, the form has to be initialized in case of the EditForm. If the dependency is only triggered when a field changes then it will only work on NewForm.

Second, changing the value for a field must trigger a re-evaluation of all the child dependencies.

Anywho... if you want to look at the code, here is a standalone example no SharePoint required if you clone the repo. The JavaScript for the tree code is here.

Let me know what you think.
Apr 1, 2016 at 12:28 AM
Works pretty good when I created my SharePoint list.

Donut instead of cake:

Cake with vanilla ice cream:

Note: I only tested with Dropdown choice fields right now.
Apr 5, 2016 at 5:40 PM
Edited Apr 5, 2016 at 6:05 PM
Hello! I just had some time to look at this and it is fabulous! Thank you!

I have a couple of questions and a comment:

Question 1: I know you said right now you've only tested it with dropdowns. I have a checkbox field/column that is the top level of three different trees. Any advice on how to get it to work with checkboxes? I've been playing around with a few things, but nothing seems to be working.
Question 2: Can hasValue take multiple dependencies? That might be part of my problem in the above question.
Question 3: If we can get the Checkboxes to work (I'll keep trying to solution for that too). Would there be a way to add a "contains" version of this (meaning if the value "contains" "xyz"? This would help with checkboxes since they concatenate the different options.

Update: I see the portion that creates the listener for the dropdown. I'm self-taught, so sometimes I'm a little slow. I'll look at this more specifically now.

Comment: I added to the hide function "node.field.SetValue('');" just in case someone sets the value of a child and then changes a parent to hide it.

I'll let you know if I figure anything else out. Again, thank you so much, this is spectacular!
Apr 5, 2016 at 8:24 PM
Edited Apr 5, 2016 at 8:44 PM
So after further use/testing I am running into the same problem that my functions were running into. When a field is dependent on more than one field or dependent on multiple items within a single field only the last item results in a true statement (which makes sense).

This is the logic I am trying to mimic:

So ultimately the whenField and hasValue would need to take in arrays like the showFields does. It would then need to return true if ANY of the values are true.

pcpTree.whenField('How many scoops?').hasValue('2').showFields(['Here's your packed taco']);
pcpTree.whenField('How many scoops?').hasValue('3').showFields(['Here's your packed taco']);
pcpTree.whenField('How many scoops?').hasValue('4+').showFields(['Here's your packed taco']);

In the above example, only the '4 +' reveals the 'Here's your packed taco' field. I know I can put them into an if/else if tree, but that nearly defeats the purpose of this exercise :) My thinking is that we just have to use the same recursion you are using in the showFields function. Am I thinking correctly?
Apr 5, 2016 at 8:35 PM
Glad you like it. =)

Q1: Looks like you found this already. I've thought some about this and it should be possible to attach the callback dynamically based on the field's type. The properties are already set in the SPField object by SPUtility, for example: Dropdown (choice), Textbox (text, number, etc.), Checkbox (yes/no), Checkboxes (choice) and more.

Q2: Right now hasValue supports one and only one value. Do you mean a field has a dependency on multiple values in one field? Or a dependency on one value in multiple different fields?

Q3: For a multi-select choice field it will have a Checkboxes property. We should be able to loop through all the checkboxes and assign the callback to each one. We can definitely add a "containsValue" method.
Apr 5, 2016 at 8:40 PM
Just saw your update. I think you're right... we'll have to make whenField and hasValue take arrays as well.

Let me think about this, all this talk about tacos is making me hungry. :)
Apr 6, 2016 at 2:32 PM
My original idea was to create multiple arrays for the multiple dependencies. The fields with single dependencies would effectively be arrays with one item.

Using my example above it would looke something like this

Parent field = 'How many scoops?'
Parent values = ['2', '3', '4+']
Child array = ['Here's your packed taco', 'Here's your packed taco', 'Here's your packed taco']

When you find the corresponding value in the parent values array it shows the corresponding child array field.

I just have one issue:
I can't figure out how to account for multiple parents (i.e. 'Do you want sour cream?','Do you want vegetables?' being the parents of 'Do you want guacamole?' in the above example.) I feel like we're going to run into the same problem as before (only the most recently checked value returning true/false).
Apr 7, 2016 at 3:54 AM
Yeah I've been thinking about this and I think we're going to need a directed acyclic graph. Reason is, once you figure out how to keep track of multiple parents the next problem is preventing circular dependencies. The values make it a bit more complicated but should not be hard to implement once we have the graph.

I'm hoping to have some time this weekend to work more on it.