简体   繁体   中英

rails link_to delete without ujs, using only jQuery

I'm trying to do exactly what jquery_ujs is doing but, without ujs. I have one link app, just one, which posts to a destroy action. I want to avoid using ujs for performance purposes. I tried generating a form using jQuery when the link is clicked on submitting using ajax. The problem is, the action redirects the browser to logout. I am able to hit the controller just fine but nothing happens on the browser side. I'm aware button_to solves this as well, but i can't use a button. I have hardcoded the form data for clarity

$(document).ready(function() {
  var csrf_token = $('meta[name=csrf-token]').attr('content');
  var form = $("<form action='/app/logout' class='logout-form' method='post' accept-charset='UTF-8'></form>")
  var input1 = $("<input name=_method' type='hidden' value='delete'>")
  var input2 = $("<input name=authenticity_token' type='hidden'>").val(csrf_token)
  form.hide().append(input1)
  form.submit(logout)
  $("a[data-method]").click(function(event){
    event.preventDefault()
    form.submit()
  })

  function logout(event) {
    $.ajax({
      url: '/app/logout',
      type: 'POST',
      data: {_method:"delete", authenticity_token: csrf_token, action: "destroy", controller: "internal/logins" }
    })
    event.preventDefault()
  }
});

The code above constructs a form, which is submitted on a click event

link_to("Logout", logout_path, :method => :delete)

An ajax post to a destroy action which redirects to another site causes CORS error. Solution is to construct a form, the same way button_to does and just use jquery submit.

    var link = $("a[data-method]");
    function submitForm(){
       var csrfToken = $('meta[name=csrf-token]').attr('content');
       var csrfParam = $('meta[name=csrf-param]').attr('content');
       var form = $('<form method="post" action="' + link.attr('href') + '" type="hidden" class="logout-form"</form>');
       var metadataInput = '<input name="_method" value="' + link.data('method') + '" type="hidden" />';
       metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
       form.append(metadataInput).appendTo('body');
       form.submit()
    }
      link.click(function(event) {
        event.preventDefault();
        submitForm()
      });

I realized I initially had my link_to function remote option set to true, which wasn't working. Just left it as is, add an on click listener and submit form when clicked, then preventDefault

link_to("Logout", logout_path, :method => :delete, class: 'logout')

I can't comment, but the first answer is correct, but has a bug: the link used in submitForm will only be the first link matched. Here's what my version looks like:

$('a[data-method]').click(function() {
   var $link = $(this);
   var csrfToken = $('meta[name=csrf-token]').attr('content');
   var csrfParam = $('meta[name=csrf-param]').attr('content');
   var $form = $('<form method="post" action="' + $link.attr('href') + '" class="u-hiddenVisually"></form>');
   var metadataInput = '<input name="_method" value="' + $link.data('method') + '" type="hidden" />';
   metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
   $form.append(metadataInput).appendTo('body');
   $form.submit();
   return false;
});

Replace class: 'u-hiddenVisually' with whatever you use to hide the form.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM