Firing an Event When a User Selects a Value from a Data View Web Part Dropdown

I was skimming my old postings, and I realized that in a previous post, I had said that I would post about firing an event when a user selects a value from a DVWP dropdown.  Better late than never, I guess.

When you create a dropdown type of DVWP through the UI in SharePoint Designer, the dropdown is created just fine, but there is absolutely nothing there to make that dropdown actually *do* anything.  Helpful, but not much.  Here’s how you can make it worth something.

In this example, my goal was to pass the chosen value to another page through the query string (There are other ways to do this, but for this client, there was auditing software that made having the value in the URL of use.) so that I could display the set of items that were created during a specific archive period.  (I had a calculated column that gave the archive period based on the published date — see this post on how that works.)

  • Add a DVWP to the page
  • Drop the column you want to see onto it
  • Change layout and choose the second from the bottom option — Dropdown menu of titles

To get at the query string variable ArchivePeriod (seen in the code below referred to as $ArchivePeriod) you go to the DVWP ‘Common Dataview Tasks’ (click on the little > button to the right on the DVWP), and set up a Parameter as seen in the screen snippet below.  If you search the code for the page for ArchivePeriod after doing this, you can see the effect of your actions.  You can, in fact, add the variable directly into code, as you see! (There are two lines for ArchivePeriod now.)

Data View Parameters

The key portions of the code that SharePoint creates when you add this DVWP to the page as in the three steps above are as follows:

<xsl:template name="dvt_1">
...
<select name="ID" size="1">
<option selected="true" value="0">Choose One...</option>
<xsl:call-template name="dvt_1.body">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="1" />
<xsl:with-param name="LastRow" select="$dvt_RowCount" />
</xsl:call-template>
</select>

and

<xsl:template name="dvt_1.rowview">
<option>
<xsl:value-of select="@Archive_x0020_Period" />
</option>
</xsl:template>

While Designer has created a nice dropdown for you, nothing will happen if you make a selection; that work is left to you.  Here are the changes that I made; I’ve explained the changes below.

<xsl:template name="dvt_1">
...
<select size="1" onchange="HandleFilterSelection('default.aspx', 'PageFilterArchive.aspx', 'ArchivePeriod', this.options[selectedIndex].value)">
<xsl:choose>
<xsl:when test="not(string-length($ArchivePeriod))" >
<option value="0">Choose Dates</option>
</xsl:when>
<xsl:otherwise>
<option value="*">All Dates</option>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="dvt_1.body">
<xsl:with-param name="Rows" select="$Rows" />
</xsl:call-template>
</select>

<xsl:template name="dvt_1.rowview">
<xsl:variable name="NewGroup" select="ddwrt:NameChanged(string(@Archive_x0020_Period), 0)" />
<xsl:if test="string-length($NewGroup)">
    <option>
<xsl:if test="$ArchivePeriod = @Archive_x0020_Period">
<xsl:attribute name="selected">
<xsl:value-of select="selected" />
</xsl:attribute>
</xsl:if>
<xsl:attribute name="value">
<xsl:value-of select="@Archive_x0020_Period" />
</xsl:attribute>
<xsl:value-of select="@Archive_x0020_Period" />
</option>
</xsl:if>
</xsl:template>

function HandleFilterSelection(defaultpath, filterpath, parameter, selection)
{
if(selection == "*")
{
document.location.href = defaultpath;
}
else
{
document.location.href = filterpath + "?" + parameter + "=" + selection;
}
}
  • Line 3: Adding the onchange event allows you to provide an action if the value in the dropdown changes.  I decided to handle this in an externally stored Javascript function called HandleFilterSelection so that I could reuse it easily.
  • Lines 4-11: This xsl:choose lets me alter the prompt based on whether there is currently a filter in place or not.
  • Lines 18-19: This code lets me test to eliminate duplicate values.  This works because I have the list items sorted in descending order by Publish Date.
  • Lines 22-24: If the value is the currently selected value (i.e., it is driving the current filter on the page), this code lets me set it as the selection in the dropdown.
  • Lines 26-28: Unless you specifically set the value that will be returned for the selection, it’s an unpredictable number.  By setting it to the actual text of the selection, we can ensure the it is both recognizable and unique.

UPDATE 2009-05-01 — As a response to Patrick’s question below (It’s hard to include code in a comment.):

In my example, the HandleFilterSelection JavaScript was stored externally from the page because I used it in many places.  (I usually create a Document Library in the root site of the Site Collection called JavaScript to store .js files. I then include them in the pages where I want to use them by adding a <script src=”blah.js”> into the page.)

You can have the onchange event for the select do anything you want.  For example, I often just call the same page with a Query String parameter, like in the code snippet below:

<select name="SelectFluid" size="1">
<xsl:attribute name="onchange">
document.location =
&apos;<xsl:value-of select="$URL"/>&apos; +
&apos;?F=&apos; + this.options[selectedIndex].value;
</xsl:attribute>

To have this work, declare a parameter in the ParameterBindings section for the URL server variable (see my post entitled Data View Web Part Parameters Based on Server Variables for more on using IIS server variables):

<ParameterBinding Name="URL" Location="ServerVariable(URL)" DefaultValue=""/>

and then declare the parameter at the start of your XSL:

<xsl:stylesheet [...]>
<xsl:output method="html" indent="no"/>
<xsl:param name="URL"/>

Similar Posts

52 Comments

  1. I have DVWP dropdown. It opens a word document correctly based on the the drop down selected and the value in Column4. My question is how do I open word document and have the Document Properties field Title filled in with the value in Column2. Would appreciate any tips. I’m new to DVWP’s. Thanks.

    Drpdwn

    Choose One…

  2. Marc,
    I am hanging a lot of hopes on this post! It’s the only one I have found after days to trying to get help on enabling an action on selection of a value in a drop-down style DVWP.

    Unlike your example, my list will always have unique values, so there is no need to allow for duplicates. My list consist of 400+ vendors (vendor numbers and vendor names).

    There is another field that is a concatenation of number and name, and that is the value that appears in the drop-down. It shows both (this is because users can’t memorize 400 vendors based solely on their numbers :-)

    On selection, the user should be taken to an .aspx web part page via query string. The URL of this page needs the “number” parameter, so for example, choosing a drop-down value “500A- Smith Company” takes the user immediately to http:site/subsite/vendordata.aspx?number=500A, whch shows them all the data for the Smith Company. So the parameter that is passed is different than the value that is populating the drop-down.

    Can you help me with adapting your code in this post to make this happen? Please email me personally if that is easier. Thanks so much!

    1. Nancy:

      Your example is a little bit simpler, not not really much. You code will need to look something like this. (I’ve just typed this out, not testing at all, but you should get the idea.) I’ve removed the calls to external JavaScript functions because you don’t really need them; that’s just how I built it originally.

      Note that having 400 values in a select is a pretty poor user experience. You’ll probably want to rethink this.

      M.

      <xsl:template name="dvt_1">
        ...
      <select size="1" onchange="document.location.href = 'http://site/subsite/vendordata.aspx?number=' + this.options[selectedIndex].value)">
        <xsl:call-template name="dvt_1.rowview">
          <xsl:with-param name="Rows" select="$Rows" />
        </xsl:call-template>
      </select>
      
      <xsl:template name="dvt_1.rowview">
        <option>
          <xsl:attribute name="value">
              <xsl:value-of select="@VendorNumber" />
          </xsl:attribute>
          <xsl:value-of select="concat(@VendorNumber, ' - ', @VendorName)" />
        </option>
      </xsl:template>
      
  3. Marc- I agree that 400 items in a drop-down is about 395 too many- but that’s what they asked for. Guess what happened when they saw it in action? Exactly.

    But I still want to know how to accomplish this so thank you for your reply!!

  4. Marc this is exactly what I have been looking for, thank you so much for publishing.

    I am using this to enable a cascaded filter by using it with a standard asp dropdown, the only issue I have is the selection is lost during the post-back of the asp dropdown field (which is used to as a control to filter the webpart dropdown.)

    Is there any way I can rectify this?

  5. Marc, any idea what happened to the Dropdown layout option in SPD2010? I don’t see it as a choice anymore. Do you have a recommended approach to replace this technique? I have a lookup list with 20 items that i would like to display in dropdown to act as a filter for another list on a page. I actually have 4 lists that i want to connect together.
    TIA
    Dean

    1. Dean:

      I rarely used those layouts even in 2007 because I found I needed to rewrite the XSL most of the time, anyway. All the dropdown layout does is to emit a select, with the individual items as options in that select.

      M.

  6. Marc.. this is something very close to what we need to implement in a DVWP.. The requirement is if a user chooses a particular choice
    (say “Development” for a Project status), then need to check if another field (say “Number of days” ) has any data. If the
    “Number of days” field has no data, then need to issue a message and disable the update button. I’ve been trying to implement this
    logic for DVWP last couple of days with no success. Similar edit had to be done in a List view Webpart and it was easier to accomplish using JQUERY and hidden CEWP. If you have any suggestions as to how we can enable the edit check in a DVWP, it’ll be really helpful. Thanks for your time.

    1. Suj:

      You’re still going to have to use script if you want the check to happen client side. Otherwise, you’ll have to write a validate server side.

      M.

  7. This works great, but something I haven’t been able to figure out is how to get 2 filters to work at the same time. So dropdown a filters the results, and then if they select something in dropdown b, it also filters the list maintaining what they selected in dropdown a.

    somehow we have to add to the query string right? If I manually type in the query into the address bar, it works. So I know that part works.

    Any ideas?

      1. Hi Marc,
        Not so much cascading dropdowns, I’m not trying to filter results in another dropdown.

        Basically I have 3 dropdowns on my page. That filter different columns in my list, but they don’t work together. So If I choose something in first dropdown, my results are filtered. but if the user then wants to additionally filter on another column using dropdown 2. When they make the selection, it requeries the list and they get the new results of dropdown 2. But what they had selected in dropdown 1 is no longer there or being filtered on.

        I think all I need to do is somehow build the query string to include both, I just can’t figure out how to do it.

        Because if I manually put something like this in my address bar, it works

        mypage.aspx?username=chris&archived=yes

  8. Hi Marc,
    I have a form which users have to filled out. I have managed to use your auto populate script to get auto population to work for the login user information. What I need is to add a button or even a drop down so when user click or select should add other user’s from people’s picker who are not necessary login and auto populate. I can create this in .net using dynamic controls but my client want this in sharepoint 2010. Any help.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.