Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

Conditional Default Values

Conditional Default Values

  • Comments 24

Sometimes you want the default value of a field to be dependent upon a condition. However, there isn’t any direct functionality to support IF statements in the default values of fields. Substituting a rule for a default value only gets you so far, as the rule is only applied when that field that changes, not the fields that the rule depends on. Updating the field whenever any dependent field is changed would require you to copy the rule to each field.  This is not very maintainable, so below I will describe two approaches to avoiding this.

The first approach is simple, but it has some limitations and caveats.  The second approach is more complicated, but should work in all cases. 


Method 1: Using the union and array indexer operators

The first approach is to use the union operator ‘|’ along with an array indexer ‘[]’ to select the proper value.  For example,

if (BoolCondition) {
   TrueResult
} else {
   ElseResult
}

becomes

(TrueResult | ElseResult) [(BoolCondition) + 1]

You can see that (TrueResult | ElseResult) creates a node set, while [(BoolCondition) + 1] selects which node to choose.  BoolCondition will evaluate to 0 or 1 (depending on its truth value).  Then 1 is added because the node set is 1-based, not 0-based. 

As a simple example, say that you want to set field3 to field2 if field2 is 10 greater than field1; otherwise set field3 to field1.  On field3’s default value, the expression would be

(../my:field1 | ../my:field2)[( ../my:field2 > ../my:field1 + 10) + 1]

 

There are two caveats to using this approach:

1) The node set will always be returned in document order. It does not matter what the order is in the parenthesis, as (field1 | field2) == (field2 | field1). Since you cannot change the node set ordering, you may have to modify your BoolCondition to be NOT-ed. For more information on document order, you can visit the w3.org page on XPaths.
2) Inside of the parenthesis, you must only have nodes; you cannot have strings or any other type. So (field1 | “hello world”) will not work.


Method 2: Using concat, substring and string-length

To overcome these caveats, you can use the second approach here.  That is to use concat, substring and string-length.  For example, the same generic if statement from the previous approach converts to

concat(

substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),

substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult)))

The key here is that BoolCondition will evaluate to 0 or 1.  Therefore, the first substring will either take no characters (if BoolCondition is false), or it will take all of the characters (if it is true) of the TrueResult.  Conversely, the second substring is evaluated with the “not” condition.  Therefore, either the TrueResult or the ElseResult will be returned in their entirety, but not both. 

Let’s say that we want to use the same example as the first approach above,

concat(

substring(../my:field2, 1, (../my:field2 > ../my:field1 + 10) * string-length(../my:field2)),

substring(../my:field1, 1, (not(../my:field2 > ../my:field1 + 10)) * string-length(../my:field1)))

The major advantage to this approach is that you can use strings, numbers or anything else as the TrueResult and ElseResult.  For example, we could have placed “Success” and “Undefined” instead of ../my:field1 and ../my:field2. 

That is all you need to create conditional statements in your default values! I'm attaching a sample form template that has this technique implemented (save the XSN locally before opening it). This method works on InfoPath 2003, 2007, and in browser-enabled form templates. 

Thanks to Alexei Levenkov and Gary Hsu for their assistance on this article. 

Nicholas Lovell
Software Design Engineer

Attachment: ConditionalDefaultValues.xsn
Leave a Comment
  • Please add 2 and 8 and type the answer here:
  • Post
  • There could be a third caveat for the first approach: it might cause extra postbacks in browser-enabled form templates (something to be verified). Form performance is always an important consideration for those so sometimes a more cumbersome method could yield fewer postbacks.

  • Similar to performing elapsed time calculations, creating a new date or time value based on a previous

  • When the BoolCondition is a bool xml element which can be null, the result of Method 2 will be an empty string.

    To resolved this problem, the condition should be modified like this:

    concat(

    substring("Yes", 1, not(not(IsTrue)) * 3),

    substring("No", 1, not(IsTrue) * 2)

    )

    The double not() function will convert null value to false, then the result will be right.

  • For selecting the default values this does work as desired, however if the user then changes the field value, it will revert back to the True or false value accordingly. There are no rules applied nor data validation being applied. Why will it not accept the new value and why would it possibly be revering back to resulting default value?

  • Excellent post. Another caveat to Method 1....the expression is not supported by Form Server (MOSS 2007). The expression in Method 2 is however.

  • UPDATE: Due to the number of requests for adding more columns to this sample, I have re-designed how

  • Not sure if you can help me, but I am trying to work with a repeating table from a Batch data source and I want the table to automatically populate with values already existing on the form. The problem is that on this repeating table I cannot see on the Design side all the fields in the revolving table...It automatically picks up the field names from the Batch file when I do a preview.

    What i would like to be able to do is say:

    when FieldName="Title" then FieldValue=Field1

    when FieldName="FirstName" then FieldValue=Field2

    ....

    but it tells me that FieldName (it writes it as @Name) is not a valid field or group (probably because it is not assigned a specific value, it contains 4-5 rows).

    Is there any type of logic I can write to fix this issue?

    Thanks,

    Elena

  • Hi Elena,

    I provided an answer to this quesstion in the Submitting to a SharePoint list post.

    Scott

  • I believe there is also Method 3 in addition to Method 2 where you can do the same but without error prone hardcoding of symbol positions. I have the working example here:

    http://alecpojidaev.wordpress.com/2009/07/06/how-to-check-if-your-form-is-dirty/

  • Hi (Scott ?)

    I adopted the example with the concat and substring function to the following:

    concat("Inbetriebnahme der "; tbxGerInfName; " Firewall des Herstellers "; tbxGerInfHersteller; "."; substring("Softwareupdate auf die Version " + tbxGerInfSWVersion; 1; (string-length(lbxGerInfSWUpdate) = 2) * string-length("Softwareupdate auf die Version " + tbxGerInfSWVersion)); substring(" "; 1; (not(string-length(lbxGerInfSWUpdate) = 2)) * string-length(" ")))

    But I always get following output:

    Inbetriebnahme der "tbxGerInfName" des Herstellers "tbxGerInfHersteller".NaN

    So the first sentence is absolutly right. But what's the meening of "NaN" in the second sentence?

    Walter

  • Hi Walter,

    "NaN" means "Not a Number" - so your expression is returning something that is not recognized as numeric value.

    Scott

  • OK, and do you know what might be the reason for this in the snippet above?

    Walter

  • Hi Walter,

    Not offhand...so I would suggest starting fresh with your expression and just bring in the parts piece-by-piece to see where it fails.

    Scott

  • Along the lines of conditional values- I am creating a form to be accessed in a browser and I am trying to set conditional formatting. I want to make a set of check boxes appear if one certain check box is checked (for instance field 1 is a check box- if they check box 1- fields 2 and 3 appear and are also check boxes). I have tried to set a rule and it's not letting me. Please help!

  • The disconnect between InfoPath 2010 and SharePoint seems very large.  IF statement functionality is allowed for default values in Sharepoint list fields.  Simply opening a form in InfoPath, making a minor layout change and publishing, breaks your default value because InfoPath 2010 does not allow IF statement functionality.

    Metadata fields don't even try to work in InfoPath 2010.  As a customer, it's very disheartening when you want to make a simple change in Sharepoint and it forces you to open up another tool (in this case InfoPath), and then the tool does not have what the user sees as basic functionality, or the functionality is completely different.

    It seems like the Sharepoint and InfoPath teams at Microsoft are working independently of each other, and there's a major disjoint between the products.  Which, a user is expecting to be seemless between the products because SP forces InfoPath on the user.

Page 1 of 2 (24 items) 12