Simon, thanks for your comment. I had not considered the form-in-a-form case. But, now that I think about it, I don't think it's as limiting as
it might seem. Let me explain.
When we want to trigger an action and we're already inside of a form,
there are really two cases to consider. The first case is when the
action depends on the state of the entire form. This case is actually
the common case for plain old forms: Click a submission button and the
entire form is processed. For this case, just create a submission
button with the usual X/HTML markup:
<input type="submit" value="Process your Order"/>
No need to use
button_to or anything like it. Normal markup works
just fine.
The second case is the interesting one. It's when we want the action
to operate only upon local state, acting in effect as an escape hatch
from the form. (E.g., consider the Add To Cart buttons in Amazon Wish
Lists.) That is, we do not care about the state of the entire form,
just the local context of the action (e.g., a particular item in the
wish list to add to the cart). This is where many people turn to
hypertext links, encoding the local state into the URL. But there are
other options.
One option is to use a normal form-submission button, just like in the
common case, but with a twist: We additionally encode the local state
into the button (e.g., via its name attribute). When the server
processes the request, it simply ignores the form state and processes
the encoded local state. The downside is that if the form state is
large, the POST requests will be correspondingly wasteful.
Nevertheless, in many cases the waste may be within acceptable limits.
Another option is to use a link inside of the form to confirm –
not to trigger – the local action. The link points to a
confirmation page that summarizes the action to be performed in a
form. If the user confirms the action, the form is posted, triggering
the action. The upside is that if the action is potentially unsafe,
users will have a real opportunity to confirm it (which
Javascript-based approaches do not guarantee). The downside is that
if the typical usage scenario involves a user having to perform the
action frequently, the confirmation round trips may become burdensome.
(On the other hand, if that's the typical scenario, we might be better
off redesigning the interface to allow for batch operations.)
Yes, the corner case does exist. But it's not as big as it initially
seems.
Cheers,
Tom