Welcome to MSDN Blogs Sign in | Join | Help

InfoPath Team Blog

Tips and tricks to get the most out of Microsoft InfoPath

News

  • For questions, comments, and feedback please use the public newsgroup: microsoft.public.infopath
    This is provided "AS IS" with no warranties, and confers no rights. Use of included script samples and forms are subject to the terms specified in the Terms of Use.
Conditional Default Values

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

Posted: Monday, November 27, 2006 5:56 AM by infopath
Filed under:

Attachment(s): ConditionalDefaultValues.xsn

Comments

DavidAir said:

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.

# November 28, 2006 2:23 AM

InfoPath Team Blog said:

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

# February 20, 2007 12:38 PM

Lixinfeng said:

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.

# March 23, 2007 7:08 AM

jeff.arrington said:

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?

# September 13, 2007 11:01 AM

JasonEley said:

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

# January 12, 2008 10:33 PM

InfoPath Team Blog said:

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

# August 18, 2008 5:23 PM

ElenaS said:

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

# April 7, 2009 2:16 PM

infopath said:

Hi Elena,

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

Scott

# April 7, 2009 3:45 PM

Elfoamerican said:

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/

# August 25, 2009 1:37 PM
Anonymous comments are disabled
Page view tracker