0

My form has two "save"-buttons - one for saving and redirecting to the Index view, and one for saving and returning to the Edit view.

With mouse click operation it works as it should, but I want to be able to press CTRL+S to save and redirect back to the Edit view.

This is the Edit form:

<form asp-action="Edit" id="myForm">
    <!-- more form items -->
    <button type="submit" name="save" value="">
        Save and go to index
    </button>
    <button type="submit" name="save" value="stay">
        Save and stay here
    </button>
</form>

This is the controller method:

public async Task<IActionResult> Edit(int id, string save, [Bind("form fields")] Model model)
{
    // save form data and stuff

    if (save == "stay") // "save" is the name of the submit buttons
    {
        return View(auto.Map<ViewModel>(model));
    }
    else
    {
        return RedirectToAction("Index");
    }
}

This is the key handling jQuery:

$(window).bind('keydown', function(event) {
    if (event.ctrlKey || event.metaKey) {
        if (String.fromCharCode(event.which).toLowerCase() == 's') {
            event.preventDefault();
            $("[name=save]").val('stay');
            $("#myForm").submit();
        }
    }
});

As you can see, I am setting the value for the submit-button to "stay", in an attempt to get returned to the Edit-view after save, as per my controller method logic, but I get redirected to the Index-view anyway.

If I mouseclick the "stay"-button, the value "stay" is received by the controller. If I keypress CTRL+S, it is not.

Stian
  • 1,522
  • 2
  • 22
  • 52

2 Answers2

1

Values set on a button are only sent on click. They are not included when using .submit(). This is expected behaviour.

Simple solution would be to manage this with a handler which will work in lieu of your existing keydown binding.

<form id="myForm">
  <input type="hidden" name="save" value="" />
  <button type="submit" data-save="">Save and go to index</button>
  <button type="submit" data-save="stay">Save and stay here</button>
</form>

Notice we've removed the name/value attributes and can now utilise the hidden input which will always be sent to the server.

$(':submit[data-save]').on('click', function (event) {
  event.preventDefault(); // 1
  const saveValue = $(this).data('save') || ''; // 2
  $('[name=save]').val(saveValue); // 3
  $('#myForm').submit(); // 4
});

In a nutshell...

  1. event.preventDefault() prevents the button submitting the form
  2. saveValue is set to whatever we've declared in the data attributes
  3. updates the hidden input with the associated value
  4. submits the form

Your keydown binding will still work, untouched.

Cue
  • 2,699
  • 1
  • 12
  • 13
1

There are two buttons here, so I'm unclear which you're trying to change, or both, but this code sets the value attribute of both buttons to "stay" when ctl + s is pressed. Did this with help from this answer:

How to detect if multiple keys are pressed at once using JavaScript?

$(window).bind('keydown', onkeydown);
$(window).bind('keyup', onkeyup);

var map = {}; // You could also use an array
onkeydown = onkeyup = function(e) {
  e = e || event; // to deal with IE
  map[e.keyCode] = e.type == 'keydown';
  if (map[17] && map[83]) { // CTRL+s
    $("button[name='save']").each((i, e) => {
      $(e).val("stay");
    });
    console.log("success");
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>Click in this window and press ctl + s</h2> 
<form asp-action="Edit" id="myForm">
  <!-- more form items -->
  <button type="submit" name="save" value="">
        Save and go to index
    </button>
  <button type="submit" name="save" value="stay">
        Save and stay here
    </button>
</form>
symlink
  • 11,984
  • 7
  • 29
  • 50