GeoffM
GeoffM

Reputation: 1611

Razor, two forms, same field

Form 1 is a set of filters, and the "submit" button applies those filters to a GET method. Form 2 is a set of data, and the "submit" button saves that data and also continues the filters via a POST method. The filter options are passed back and forth - the user GETs the initial page, possibly sets up some filters which GETs the same page again in terms of controller method, then the user can modify some data and save via a POST, which then returns back with a GET for the same filtered page.

Simplified (lots more that is likely to be irrelevant):

@model PagedList.IPagedList<xxx.Models.WttPlatformGridRow>

@using (Html.BeginForm("PlatformGridEdit", "Wtt", FormMethod.Get))
{
  @Html.CheckBox("ExcludeThrough", (bool)ViewBag.ExcludeThrough)
  <input type="submit" value="Filter" />
}

@using (Html.BeginForm("PlatformGridEdit", "Wtt", FormMethod.Post))
{
  @Html.Hidden("ExcludeThrough", (bool)ViewBag.ExcludeThrough)
  <input type="submit" value="Save" />
}

Simplified controller:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PlatformGridEdit(List<WttPlatformGridRow> rows, bool? excludeThrough)
{ etc }

public ActionResult PlatformGridEdit(bool? excludeThrough)
{ etc }

Obviously naming two elements the same is illegal in HTML, and it doesn't work anyway (parameter is null in the C# method).

The answers I've seen so far suggest a single BeginForm with all the data. Fine. Except one is a GET (no data changes) and one is a POST (data changes). User need to be able to bookmark the filter so I can't handle it all as a POST anyway, otherwise the browser will ask the user if resubmitting form data is okay.

I'm also using an IPagedList which (as far as I know) precludes the use of a single model with a list field instead of using ViewBag.

Another option seems to be using client side scripting to copy the value from one field to another. But I don't see how to do this when the parameter name in the controller method is the same for both client side fields.

What is the best way of handling this please?

Upvotes: 1

Views: 143

Answers (1)

GeoffM
GeoffM

Reputation: 1611

I have a solution but I can't help thinking there must be a better way.

FWIW, this is what I've done. The two fields have non-identical names (but similar). The "master" version (visible checkbox) has script that copies the value to the "slave" version (hidden field) on submit. The controller method takes both names and decides which is relevant - one or both should be null, but both shouldn't have a value, but we handle that just in case.

Finally, the controller returns the view with the combined value (using the "master" identity).

View - form 1:

bool excludeThrough = ViewBag.ExcludeThrough != null ? ViewBag.ExcludeThrough : false;

@Html.CheckBox("ExcludeThrough", excludeThrough, new
{
    @class = "form-control",
    onchange = "document.getElementById('ExcludeThroughFilter').value = document.getElementById('ExcludeThrough').value;"
})

View - form 2:

@Html.Hidden("ExcludeThroughFilter", excludeThrough)

Controller:

public ActionResult PlatformGridEdit(..., bool? excludeThrough, bool? excludeThroughFilter)
{
    bool excThru = false;
    if (excludeThrough.HasValue) excThru = excludeThrough.Value;
    if (excludeThroughFilter.HasValue && excludeThroughFilter.Value) excThru = true;
    ...etc...
}

Upvotes: 1

Related Questions