Mike Perrenoud
Mike Perrenoud

Reputation: 67898

How to handle an edit and delete button on the same form in ASP.NET MVC?

Consider the following markup:

<h2>Edit SAS Program</h2>
@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post))
    {
        <input type="submit" class="button" value="Delete" />
    }
    <input type="submit" class="button" value="Save Changes" />
}

I'd like to have the Delete button on the same view as the Edit. However, it's not letting me have nested forms. What is the appropriate way to handle this situation?

I tried leveraging this answer, How to handle nested forms in ASP.NET MVC, but it's a broken link now.

Upvotes: 14

Views: 36279

Answers (8)

Murat KA
Murat KA

Reputation: 123

Hi dear friend you can check out this solution: https://www.dotnettricks.com/learn/mvc/handling-multiple-submit-buttons-on-the-same-form-mvc-razor

enter image description here

@using (Html.BeginForm("MultipleCommand", "Home", FormMethod.Post, new { id = "submitForm" }))
{
 <fieldset>
 <legend>Registration Form</legend>
 <ol>
 <li>
 @Html.LabelFor(m => m.Name)
 @Html.TextBoxFor(m => m.Name, new { maxlength = 50 })
 @Html.ValidationMessageFor(m => m.Name)
 </li>
 <li>
 @Html.LabelFor(m => m.Address)
 @Html.TextAreaFor(m => m.Address, new { maxlength = 200 })
 @Html.ValidationMessageFor(m => m.Address)
 </li>
 <li>
 @Html.LabelFor(m => m.MobileNo)
 @Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })
 @Html.ValidationMessageFor(m => m.MobileNo)
 </li>
 </ol>
 <button type="submit" id="btnSave" name="Command" value="Save">Save</button>
 <button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button> 
 <button type="submit" id="btnCancel" name="Command" value="Cancel" onclick="$('#submitForm').submit()">Cancel (Server Side)</button>
 </fieldset>
} 

Upvotes: 0

AdemusPrime
AdemusPrime

Reputation: 23

The OLD way to do this but still applicable is to have one form tag and change the action with multiple submit buttons.

<input class="btn btn-default" type="submit" value="Save" />
<input class="btn btn-default" type="submit" value="Delete" onclick="this.form.action='/SasProgram/delete/@Model.Id';" />

Upvotes: 0

Ramon Smits
Ramon Smits

Reputation: 2618

You can also use html 5 feature to target a form from an input button. Below I have created both a delete and save form and have the submit buttons outside of the forms but targeting them via the form attribute.

I think most browsers support this except IE.

No javascript required.

@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post, new { id = "editForm" }))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)
}

@using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post, new { id = "deleteForm" }))
{
    <input type="submit" class="button" value="Delete" />
}

<input type="submit" class="button" value="Save" form="editForm"/>
<input type="submit" class="button" value="Delete" form="deleteForm" />

This allows for a nice button layout without any fancy javascript or css styling.

Upvotes: 1

P&#233;ter
P&#233;ter

Reputation: 2181

First of all. Every modification request should be use the post method.
I make some R&D and build the basics of a multi submit button handler in a wiki A clean solution to use multiple submit button in ASP.NET MVC.
I think it could solve your problem.

Upvotes: 2

Matthew Perron
Matthew Perron

Reputation: 6291

Edit : Here's how to do it with ajax using an HttpPost.

//
// POST: /Divisions/Delete
[HttpPost, ActionName("Delete"), Authorize]
public ActionResult DeleteConfirmed(int id)
{
    Division division = _db.Divisions.Single(x => x.DivisionId == id);

    string errorMessage;
    if (DbRelationEnforcer.CanDelete(_db, division, out errorMessage))
    {
        division.SetDeleted(User.Identity.Name);
        _db.SaveChanges();
        return Json(new JsonResponseCreatePartial { Success = true }, JsonRequestBehavior.AllowGet);
    }

    return Json(new JsonResponseCreatePartial { Success = false, Message = errorMessage }, JsonRequestBehavior.AllowGet);
}

Then, on the view, you must use the <input type="submit">Save changes</input> to save your changes (within the form), and a simple link/button to delete, like this:

<h2>Edit SAS Program</h2>
@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    <input id='delete-btn' type="button" class="button" value="Delete" />
    <input type="submit" class="button" value="Save Changes" />
}

Finally, you have to use JS to post to your action from the view, when the user clicks on Delete.

<script type='text/javascript'>
    $(function() {
        $("input#delete-btn").click(function(){
            $.post('@Url.Action("Delete")', '@Model.Id', function(data) {
                if(data.Success) {
                    ' ... handle the success case
                } else {
                    ' ... error management
                }
            });
        });
    });
</script>

This will work, but in order to have a better UX, it would be preferable to have the Delete button from the Index/list view, and using a JQuery UI dialog to confirm before doing the ajax post. This will skip having to load the Edit page if/when you want to delete multiple items one after the other.

Upvotes: -1

Kristof Claes
Kristof Claes

Reputation: 10941

The best and easiest way would be to use two forms but don't nest them:

<h2>Edit SAS Program</h2>
@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    <input type="submit" class="button" value="Save Changes" />
}

@using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post))
{
    <input type="submit" class="button" value="Delete" />
}

This way you have:

  • Two separate forms
  • No GET requests
  • The delete button below the edit button, which makes more sense when you're on a view that allows you to edit something.

Upvotes: 15

Rubens Mariuzzo
Rubens Mariuzzo

Reputation: 29231

First, you cannot nest <form> element. The specification doesn't allow it. Since you are using the MVC pattern I have two options that came to my mind:

  1. You can retain the save button as the submit button of the form, and make the delete button a HTML link. Then the delete button will target to a different route, it could be something like: GET /program/delete/{id}.

  2. You can have two buttons inside the same form, then with JavaScript after clicking one of the buttons you will change the action attribute of the form.

Update

There is a third option, that is more clean: using two submit buttons with same name attribute and different values.

Your form will have two buttons:

public ActionResult MyAction(string submitButton) {
    switch (submitButton) {
        case "save":
            // ...
        case "delete":
            // ...
    }
}

For more details check this answer: https://stackoverflow.com/a/443047/439427

Upvotes: 1

nrodic
nrodic

Reputation: 3021

I would use different values for button name in the same form:

@using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
    <label for="Name">Name</label>
    @Html.TextBoxFor(model => model.Name)

    <button name="action" value="delete">Delete</button>
    <button name="action" value="save">Save Changes</button>
}

and then switch in controller:

[HttpPost]
public ActionResult Edit( SomeModel model, string action )
{
    switch( action ) {
        case "delete":
            // delete action
            break;
        case "save":
            // save action
            break;
    }
}

The code is written from memory but it works in production. Note that buttons are of default type - submit.

Upvotes: 17

Related Questions