July 2007 - Posts - David Airapetyan
in

InfoPath Dev

David Airapetyan

July 2007 - Posts

  • Showing default values from Secondary Data Sources

     Unlike the main data source, secondary data sources have an annoying property of not displaying the values stored in the XML when the view controls are bound to them. It turns out that it does not have to be this way – a small hack can fix it.

    Consider the following XML file (called data.xml):

    <?xml version="1.0" encoding="utf-8"?>

    <root>

          <data>My Data</data>

    </root>

    Let’s import it into InfoPath and bind a textbox to the "data" field:

    1.       Design a blank form (I am using InfoPath 2007 but this should work with 2003 as well)

    2.       Add an XML data connection, pick data.xml as the file, accept all the defaults

    3.       In the data source pane, switch to the "data" source and drag the data field into the view

    As a result, the text "My Data" does not show

    4.       Save as source files

    5.       Close the Designer

    6.       Open sampledata.xml which would look similar to that:


    <my:myFields ..>

          <xd:SchemaInfo ...>

                <xd:Namespaces>

                      <xd:Namespace .../>

                </xd:Namespaces>

          </xd:SchemaInfo>

          <xd:DataConnection Name="data">

                <root ...>

                      <data/>

                      <xd:SchemaInfo LocalName="root" NamespaceURI="">

                            <xd:Namespaces>

                                  <xd:Namespace .../>

                            </xd:Namespaces>

                      </xd:SchemaInfo>

                </root>

          </xd:DataConnection>

    </my:myFields>

    7.       As you can see, it contains the copy of your secondary data source but the data is not there. Now simple replace the <data/> node with the value from your XML file, namely <data>My Data</data>.

     

     

    8.       Save  sampledata.xml, open the solution in the Designer

     

    Result: now the value shows in the Designer!

     

    Warning: sampledata.xml is an internal InfoPath Designer file. Modify it at your own risk. Although I have tested the steps above and they seem to work in both InfoPath 2003 and InfoPath 2007, there is no guarantee your values will be preserved. The functionality may also change in future versions of the product.

  • Dynamic buttons in InfoPath 2003 – wrapping unbound controls with xd:preserve

    InfoPath 2007 has a lot of new great features including dynamic buttons where a button text can be specified via xpath. Unfortunately, such features are not Designer-compatible with InfoPath 2003, that is, you will be able to edit your forms alright but it won’t be possible to design them – the views containing them will be marked as "protected".

    One possible workaround is to use the xd:preserve blocks in your XSL – this works great at the cost of having to do this manually and the inability to edit the contents of those in Designer. My recommendation is to avoid using those excessively and to keep their contents as simple as possible because otherwise maintenance becomes hell. However, it’s good solution when you absolutely need to use constructs Designer does not support.

    The way xd:preserve works is via a special mode that applies to templates. Suppose you have the following piece of XSL:

    <span class="xdTextBox" xd:CtrlId="CTRL1" style="WIDTH: 130px">

    <xsl:value-of select="my:field1"/>

    </span>

    In order to wrap it in xd:preserve, you move the entire XSL into a separate template:

    <xsl:template match="my:field1" mode="xd:preserve">

          <span class="xdTextBox" xd:CtrlId="CTRL1" style="WIDTH: 130px">

    <xsl:value-of select="."/>

          </span>

    </xsl:template>

     

    Notice how the value-of’s select attribute changed to "." from "my:field1". Now, all you need to do is to replace the original XSL with the call to the newly created template:

    <xsl:apply-templates select=" my:field1" mode="xd:preserve"/>

    Although this approach works great for bound controls, it doesn’t for buttons for the simple reason that they do not have an xpath to bind to. Although you could pick some random value in the main data source it would be hacky. Also, if you have more buttons than nodes in your data source, you won’t be able to wrap them all in xd:preserve.

    The solution to this problem is to introduce a simple secondary data source with an entry for each unbound control you’d like to wrap. It’s best done with an XML file such as this:

    <buttons>

          <button1/>

          <button2/>

    </buttons>

    Now all you need to do is to use xpaths into this Secondary DOM. Assuming it’s called ButtonsPaths, the following ApplyTemplates will do the trick:

    <xsl:if test="function-available('xdXDocument:GetDOM')">

    <xsl:apply-templates select="xdXDocument:GetDOM(&quot;ButtonsPaths&quot;)/buttons/button1" mode="xd:preserve"/>

    </xsl:if>

    At this point, simply move your XSL/HTML into the button1 template and you’re done:

    <xsl:template match="button1" mode="xd:preserve">

    Your HTML goes here

    </xsl:template>

     

Copyright © 2003-2019 Qdabra Software. All rights reserved.
View our Terms of Use.