1

I'm working on an MVC project where I have several buttons posting but with a separate value so the controller know what to do as shown below.

<input type="submit" value="Reject" name="rejectHighlight" class="icon-cancel-1 btn btn-danger" />
<input type="submit" value="Archive" name="archiveHighlight" class="icon-cancel-1 btn btn-danger" />

This was all working perfectly until I added the following javascript code to handle double clicks.

$(document).on('submit', 'form', function () {
    var buttons = $(this).find('[type="submit"]');

    if ($(this).valid()) {
        buttons.each(function (btn) {
            $(buttons[btn]).prop('disabled', true);
        });
    }
    else {
        buttons.each(function (btn) {
            $(buttons[btn]).prop('disabled', false);
        });
    }
});

Now the JavaScript code works perfectly and I'm not able to double click but I've now lost my button values when it gets posted to the controller.

I'm not experienced with JavaScript and and have not been able to find an answer to correct this in my searches. Can someone please point me in the right direction on how to include the values on submit again?

Updated to show the view and controller method as shown below.

Below is the view

@model OperationHighlights.Models.Highlight

@{
    ViewBag.Title = "Edit Highlight";
}

<h2>Edit Highlight</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        @if (ViewBag.Message != null)
        {
            <ul>
                <li class="text-success">@Html.Raw(ViewBag.Message)</li>
            </ul>
        }

        <div class="form-group">
            @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.OrigGroupId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("CurrGroupId", null, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.CurrGroupId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ClassificationId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("ClassificationId", null, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.ClassificationId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextAreaFor(model => model.Description, 5, 100, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
            </div>
        </div>

        <hr />

        @if (ViewBag.SubmitReview == "Review")
        {
            <div class="form-group">
                @Html.LabelFor(model => model.Comments, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.TextAreaFor(model => model.Comments, 5, 100, new { htmlAttributes = new { @class = "form-control" } })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Save" class="btn btn-default" />
                    <input type="submit" value="Approve" name="submitHighlight" class="icon-check btn btn-default" />
                    <input type="submit" value="Reject" name="rejectHighlight" class="icon-cancel-1 btn btn-danger" />
                    <input type="submit" value="Archive" name="archiveHighlight" class="icon-cancel-1 btn btn-danger" />
                </div>
            </div>
        }
        else
        {
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Save" class="btn btn-default" />
                    <input type="submit" value="Submit" name="submitHighlight" class="btn btn-default" />
                </div>
            </div>
        }
    </div>
}

Below is the controller method

[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(int? id, string submitHighlight, string rejectHighlight, string archiveHighlight)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    Models.Highlight highlightToUpdate = db.Highlights.Find(id);
    if (TryUpdateModel(highlightToUpdate, "", new string[] { "Title", "Description", "ClassificationId", "CurrGroupId", "Comments" }))
    {
        try
        {
            if (!string.IsNullOrEmpty(submitHighlight))
            {
                // Do some work here
            }

            if (!string.IsNullOrEmpty(rejectHighlight))
            {
                // Do some work here
            }

            if (!string.IsNullOrEmpty(archiveHighlight))
            {
                // Do some work here
            }
            db.SaveChanges();
        }
        catch (DataException dex)
        {
            // Log the error
            ExceptionHandling.CreateDataErrorLog(dex, 1);

            // Alert the user
            ModelState.AddModelError("", "Unable to edit highlight. Please try again, and if the problem persists see your system administrator.");
        }
    }

    // Redirect Logic Here

}
  • 1
    You are going to need to post the full form html as well as the controller method. – nurdyguy Apr 17 '18 at 15:55
  • 2
    See this answer: https://stackoverflow.com/a/7357314/1819684 you disabled the button therefore it does not submit it's value per the spec. – gforce301 Apr 17 '18 at 16:12
  • 1
    @gforce301 - But that puts my right back where I was and allows a user to double or triple click on the button and cause multiple submissions. How would you stop multiple clicks and be able to pass data to the controller. – Phillip Kirkland Apr 17 '18 at 16:33
  • 1
    Personally I would not use "submit" type input buttons. I would use `button` elements with click handlers and submit the form via Ajax. That way you can control the action of submitting. – gforce301 Apr 17 '18 at 16:51
  • @gforce301 Thanks for the information. I have managed to capture and handle any possible multiple clicks through code for the moment. I was hoping I was simply missing something and there was a quick way to capture this globally. I have created stories to explore the option of changing the buttons as you described in a future release. – Phillip Kirkland Apr 20 '18 at 14:01

1 Answers1

2

One way of doing this is to generate a hidden input when the form is submitted:

$(function () {
    // Set up click handlers on each submit button
    $("form").find("input[type='submit']").each(function () {
        $(this).click(function () {
            $(this).closest("form").find("input[type='submit']").removeClass("active");
            $(this).addClass("active");
        });
    });
});

$(document).on('submit', 'form', function (e) {
    // Remove any added inputs (if there are any)
    $('input[name=acceptReject]').remove();
    var buttons = $(this).find('[type="submit"]');
    if ($(this).valid()) {
        // Add hidden input with name acceptReject and value of button clicked value
        $('<input>').attr({
            type: 'hidden',
            name: 'acceptReject',
            value: $(this).find(".active").val()
        }).appendTo('form');

        buttons.each(function (btn) {
            $(buttons[btn]).prop('disabled', true);
        });
    }
    else {
        buttons.each(function (btn) {
            $(buttons[btn]).prop('disabled', false);
        });
    }
});

This will submit a hidden input with name "acceptReject" with the value of the clicked submit button (either Archive or Reject).

You'll have to modify your Controller parameters and code to accept string acceptReject with these values and remove the parameters (and code) from the submit buttons.

(as noted in the comments, disabled inputs are not submitted with the form)

RickL
  • 3,318
  • 10
  • 38
  • 39