If you've ever worked on an ASP page with a lot of submit buttons, you know that sometimes
it can take some tricky coding to determine what button the user pressed when the page is
posted to the server. The problem is that there are only two ways to identify a button with
the Request object: by the value attribute (i.e., the text that appears inside the button),
and by the name attribute. The former method is useful if you have several buttons with
different text values, but you're stuck if you want to have two buttons with the same
text. The latter method enables you to have multiple buttons with the same text, but
you have to give each one a different name, which can be hard to do if you are generating
an unknown number of buttons and can't hardcode the names at design time.
Button Processing using the Value Attribute
<%
' Returns the Value Attribute
Select Case Request.Form("buttonname")
Case "One"
Response.Write "Button one pressed"
Case "Two"
Response.Write "Button two pressed"
End Select
%>
<form name="form1" action="self.asp" method="POST">
<input type="submit" name="buttonname" value="One"/>
<input type="submit" name="buttonname" value="Two"/>
</form>
Button Processing using the Name Attribute
<%
If Request.Form("One") <> "" Then Response.Write "First button pressed"
If Request.Form("Two") <> "" Then Response.Write "Second button pressed"
%>
<form name="form1" action="self.asp" method="POST">
<input type="submit" name="One" value="Button text"/>
<input type="submit" name="Two" value="Button text"/>
</form>
Relying on the value attribute seems to be the most popular of the two methods, since most pages don't
have more than one submit button with the same text. But consider this scenario: you are creating an
HTML table based on a database, and you want to give the user the option to delete an entry via a delete
button in each row of the table. How do you set up your table so it's easy to figure out which delete
button the user pressed? You could use the second method from above, dynamically generating the name
attributes based on some unique value from the database. Or you might end up doing something even
more tricky using multiple forms and hidden fields.
The old solution to the multiple-delete-buttons problem
<%
'process form submission...
'(rsUserList contains contents of userList table)
Do While NOT rsUserList.EOF
If Request.Form("cmdDelete" & rsUserList("userID")) = "Delete" Then
Call DeleteUser(rsUserList("userID"))
Response.Write "Bye, " & rsUserList("firstName") & "!"
End If
rsUserList.MoveNext
Loop
'draw form...
%>
<table>
<%Do While NOT rsUserList.EOF%>
<tr>
<td><%=rsUserList("firstname") & " " & rsUserList("lastname")%></td>
<td><input type="submit"
name="cmdDelete<%=rsUserList("userID")%>"
value="Delete"/></td>
</tr>
<%rsUserList.MoveNext
Loop%>
</table>
What if you could specifiy an arbitrary number of parameters along with each button, so you could
not only logically and easily determine which of your buttons was pressed, but you could also have
additional information passed in a simple way? The ButtonHandler class allows you to embed extra
data in the name attribute of a submit button, and access it easily after postback.
ButtonHandler.asp
<%
''
' A Button Handler is a utility object for working with buttons. It allows
' them to store more information than just a name by using a dot delimiter
' in the name attribute of the input tag.
'
' For example, you can create a series of buttons like this:
' <input type="submit" name="cmdDelete.23422341.9080" value="Add"/>
' <input type="submit" name="cmdDelete.89562331.1024" value="Add"/>
' <input type="submit" name="cmdDelete.99381200.7453" value="Add"/>
'
' In the above button, cmdDelete is the "base name," and the two numeric
' portions are "button parameters." Using a ButtonHandler, I can determine
' whether any button with a particular base name has been pressed, and
' extract the parameters.
'
' All routines in this class are functions, so that a consistent calling
' syntax can be used to access them.
'
Class ButtonHandler
'' The form that this button handler works on (a Request.Form object).
Private m_form
'' Inspector for m_form.
Public Property Get form()
Set form = m_form
End Property 'get form
'' Mutator for m_form.
Public Property Set form(p_form)
Set m_form = p_form
End Property 'set form
''
' Determines if any button with the specified base name was pressed
' on the form.
' Example:
' If bh.wasPressed("cmdAdd") Then Response.Write "User wants to add"
'
' @param strButtonBaseName the base name of a button being looked for.
' @return true if the button was pressed, false if not.
'
Public Function wasPressed(strButtonBaseName)
Dim strField 'a key in the form
wasPressed = false
'make sure a form has been provided
If NOT IsObject(m_form) Then
'no form present in m_form
Exit Function 'wasPressed will be false
End If 'is a form loaded in m_form?
For Each strField In m_form
If Left(strField, Len(strButtonBaseName)) = strButtonBaseName Then
wasPressed = true
Exit Function 'no use sticking around
End If 'if the button was present as a key in the form
Next 'strField
End Function 'wasPressed
''
' Allows the caller to get a particular parameter that was specified in
' the button name attribute.
' Parameter numbers start at 1. 0 will return the base name.
' For example, if my button name was "cmdDelete.123441.true", then
' bh.requestParameter("cmdDelete", 0) returns "123441"
' bh.requestParameter("cmdDelete", 1) returns "true"
'
' @param strButtonBaseName the base name of the button to look up.
' @param nParam the number of the parameter to retrieve, where
' 0 is the base name and 1 is the first parameter.
' @return the value of the parameter requested, or "" if
' the specified button/parameter does not exist.
'
Public Function requestParameter(strButtonBaseName, nParam)
Dim strField 'a key in the form
Dim strFoundField 'a key in the form that matches the requested base name
Dim arrFoundField 'strFoundField, split up into an array around ".".
strFoundField = ""
For Each strField In m_form
If Left(strField, Len(strButtonBaseName)) = strButtonBaseName Then
strFoundField = strField
'response.write "basename found"
Exit For 'we found a matching button, no need to look further
End If 'if the button was present as a key in the form
Next 'strField
' At this point, if strFoundField is blank, then a matching button was
' not found: return blank. If strFoundField is populated, then a
' matching button was found: look for the requested parameter.
If strFoundField = "" Then
requestParameter = ""
Exit Function
End If 'did we fail to find a matching button?
'split the field string up around the "." delimiter
arrFoundField = Split(strFoundField, ".")
If nParam > UBound(arrFoundField) OR nParam < LBound(arrFoundField) Then
'specified parameter does not exist
requestParameter = ""
Else 'i.e. specified parameter does exist
requestParameter = arrFoundField(nParam)
End If 'was the specified parameter in the valid range of parameters?
End Function 'requestParameter
End Class 'ButtonHandler
%>
Let's take a look at the ButtonHandler in action.
ButtonTest.asp
<!-- #include file="ButtonHandler.asp" -->
<%
Dim bh
Set bh = New ButtonHandler
Set bh.form = Request.Form
If bh.wasPressed("quadrantOne") Then Response.Write "quadrant one"
If bh.wasPressed("quadrantTwo") Then Response.Write "quadrant two"
If bh.wasPressed("quadrantThree") Then Response.Write "quadrant three"
If bh.wasPressed("quadrantFour") Then Response.Write "quadrant four"
%>
<form action="ButtonTest.asp" method="post">
<table border="1" cellpadding="5">
<tr>
<td bgcolor="<%=bh.requestParameter("quadrantOne", 1)%>">
<input type="submit" name="quadrantOne.red" value="Red"/>
<input type="submit" name="quadrantOne.blue" value="Blue"/>
</td>
<td bgcolor="<%=bh.requestParameter("quadrantTwo", 1)%>">
<input type="submit" name="quadrantTwo.red" value="Red"/>
<input type="submit" name="quadrantTwo.blue" value="Blue"/>
</td>
</tr>
<tr>
<td bgcolor="<%=bh.requestParameter("quadrantThree", 1)%>">
<input type="submit" name="quadrantThree.red" value="Red"/>
<input type="submit" name="quadrantThree.blue" value="Blue"/>
</td>
<td bgcolor="<%=bh.requestParameter("quadrantFour", 1)%>">
<input type="submit" name="quadrantFour.red" value="Red"/>
<input type="submit" name="quadrantFour.blue" value="Blue"/>
</td>
</tr>
</table>
</form>
Now that we've identified the basic functionality of the ButtonHandler, let's see how it performs
in the user deletion scenario:
Multiple Delete Buttons the ButtonHandler Way
<!-- #include file="ButtonHandler.asp" -->
<%
Dim bh
Set bh = New ButtonHandler
Set bh.form = Request.Form
If bh.wasPressed("cmdDelete") Then
Call DeleteUser(bh.requestParameter("cmdDelete", 1))
Response.Write "Bye, " & bh.requestParameter("cmdDelete", 2) & "!"
End If
%>
<table>
<%Do While NOT rsUserList.EOF%>
<tr>
<td><%=rsUserList("firstname")%> <%=rsUserList("lastname")%></td>
<td><input type="submit"
name="cmdDelete.<%=rsUserList("userID")%>.<%=rsUserList("firstname")%>"
value="Delete"/></td>
</tr>
<%rsUserList.MoveNext
Loop%>
</table>
It's not too much shorter, but it is more elegant. The ButtonHandler can be used on any page with buttons to make
processing more intuitive, but is most effective when you need to pass a little more data than the basic button
normally allows for. Try it on large forms, complex forms, and forms with a lot of repetition.
Download
You can download the accompanying source code for this article in zip file format from here:
ButtonHandler.zip (2.2 KB).