Tuesday, October 21, 2008

How To Blank Out A Field's Value In InfoPath Without Using Managed Code

The other day I posted some guidance on how you can effectively fake a multi-select list in browser-enabled InfoPath forms, and even showed how to show or hide another control based upon a selection in that fake multi-select list.

The next level of problem is a tricky one... Let's say you have several options in a drop-down list box that you've embedded into a repeating table, just like I described in my October 20 post. Now, if the user's selections in the repeating table make any sections with controls appear (unhide) elsewhere on the form, and the user enters data into those newly unhidden controls, but THEN they go back and modify the selections in the repeating table such that the section with controls hides again, now what?

As you probably have already discovered, that data will NOT automatically get cleared out just because the section has hidden again. The guidance generally is that you would need to write managed code to remove that data from the .xml that your form is building behind the scenes.

But, in reality, you can use Rules to achieve the desired effect. It's not pretty, in fact it's quite tedious, but it can be done.

Trial and error will very likely ensue if you read the blog posts I read trying to find answers to how to do this... So here are some quick rules of thumb:

1) If you are trying to blank out a field outside of your repeating table based upon a value selected within your repeating table, you're going to want to set a rule at the point of the repeating table control itself.

However, it is important to note that when you attach a rule to a repeating table, it will only fire when the repeating table's structure changes, such as from the insertion or removal of a row. (In fact, I still get surprising results when deleting a row from the repeating table.)

When changes are made to the answers given within one or more of the controls on a row in that repeating table, nothing will happen, despite the existence of your seemingly valid rule. What you'll need to do to account for this is to create a corresponding rule attached to the control itself. The conditions will be the same and the actions will be the same as the rule you placed on the repeating table. The key distinction is that the dropdown list box control within a column in your repeating table has its own event that triggers its rules to fire separately from the repeating table's event, and you need to cover both of these events to get the best possible results out of your rules.

2) If you are trying to blank out a field not involving a repeating table based upon a change to a non-repeating value in your primary data source, you can just put the rule at the data source layer., but are probably better off putting it at the control for the non-repeating value. That way, there is clarity about what really triggers that rule to fire.

3) Take note. You are likely going to have to repeat very similar conditions and rules in a number of places. So far, I haven't found any way to use encapsulation to limit the amount of configuration of rules required to achieve the goal here, but if I do, I'll be sure to post it.

4) Test thoroughly. Rules can make for tricky form behavior, and you need to carefully consider all of the scenarios that can occur.

Monday, October 20, 2008

Make an InfoPath Multi-Select Control That Works In Forms Services And Apply Conditional Formatting to Another Control Based On A Particular Selection

Okay, that title is a mouthful, I know, but to me the way you do this kind of thing in InfoPath is not intuitive, and therefore worthy of a blog post. It’s actually quite easy to do once you’re informed, so I’ll skip the small talk and get to it.

First of all, the scenario. I was trying to give my users a multi-select list control even though I’m working in Forms Services within SharePoint, and then show some additional form controls based on particular selections made in the multi-select list.

As you know, the standard InfoPath multi-select control is not compatible with Forms Services (no, really, I’m serious – it’s not), and although there are some good posts out there on how to achieve the same basic effect using checkboxes (http://blogs.msdn.com/infopath/archive/2004/04/01/106039.aspx ), that didn’t seem like a wise choice to me, since my option list contains more than 100 entries. Checkboxes would just take up too much screen real estate to be practical.

So, the answer for me in such a scenario is the Repeating Table control.

First, I create my Data Source structure (words to live by, btw) as follows:

Next, I drag the RepeatingTableOptions node over to my Design area and pick the Repeating Table option for control type.

Then, I drag “HideSection_Dependent Field” over to the Design area, and select “Section With Controls” as the control type.

For my purposes, I want a dropdown list box control in the repeating table instead of a textbox which InfoPath dropped in there by default, so I right-click the textbox, and select Change To Dropdown list box.

The dropdown list box control needs some data in it, so I put some values in there by right-clicking the drop-down list box control and clicking “Drop-Down list box properties…” In my real-world scenario with 100+ options, I use a SharePoint list to seed the dropdown, but for this example, we can just choose the “Enter list box entries manually” option. I click “Add” and add a list that includes “Dog,” “Goldfish” and “Hermit Crab.”

Next, I right-click the textbox control labeled “Dependent Field” and Change To Dropdown Listbox control. I right-click again and choose Drop-down List Box Properties. I add some manual entries here too, “Cockapoo”, “Labradoodle” and “Schnoodle.”

By now, you probably know where I’m going with the Dependent field... If the user selects “Dog” for the Repeating Field, I want the Dependent Field to become visible. Otherwise, it should remain hidden.

So, finally, I right-click on the Section containing the Dependent Field, and click “Conditional Formatting.” I create the single rule shown below, which basically says if the user’s selections do not include “Dog” then hide this “Dependent Field” section. You’ll notice right off (it took me a lot of trial and error, sniff sniff) that it’s not the Leaf node, nor the Options node, but in fact the Group we created one step above the Options list that is the one that is tested by the rule.

By the way, if you use Options or Leaf, at a quick glance, you might appear to have success, but you’ll find that it only tests the first row of the table in those scenarios, which misses the whole point. If the user selects “Dog” in the second row of the table, the dependent field needs to be able to recognize it just the same.

So there you have it.

You can preview the working example you just created in InfoPath, but since we’re really trying to work around the lack of multi-select list support in Forms Services, deploying it to a SharePoint site is going to be the real test.

Please drop me a note if you found this post helpful.