Skip to content

Instantly share code, notes, and snippets.

@JeffreyWay
Last active April 6, 2024 20:12
Show Gist options
  • Save JeffreyWay/5112282 to your computer and use it in GitHub Desktop.
Save JeffreyWay/5112282 to your computer and use it in GitHub Desktop.
Want to send a DELETE request when outside of a form? This will handle the form-creation bits for you dynamically, similar to the Rails implementation. (Requires jQuery, but doesn't have to.) To use, import script, and create a link with the `data-method="DELETE"` attribute.
/*
<a href="posts/2" data-method="delete"> <---- We want to send an HTTP DELETE request
- Or, request confirmation in the process -
<a href="posts/2" data-method="delete" data-confirm="Are you sure?">
*/
(function() {
var laravel = {
initialize: function() {
this.methodLinks = $('a[data-method]');
this.registerEvents();
},
registerEvents: function() {
this.methodLinks.on('click', this.handleMethod);
},
handleMethod: function(e) {
var link = $(this);
var httpMethod = link.data('method').toUpperCase();
var form;
// If the data-method attribute is not PUT or DELETE,
// then we don't know what to do. Just ignore.
if ( $.inArray(httpMethod, ['PUT', 'DELETE']) === - 1 ) {
return;
}
// Allow user to optionally provide data-confirm="Are you sure?"
if ( link.data('confirm') ) {
if ( ! laravel.verifyConfirm(link) ) {
return false;
}
}
form = laravel.createForm(link);
form.submit();
e.preventDefault();
},
verifyConfirm: function(link) {
return confirm(link.data('confirm'));
},
createForm: function(link) {
var form =
$('<form>', {
'method': 'POST',
'action': link.attr('href')
});
var token =
$('<input>', {
'type': 'hidden',
'name': 'csrf_token',
'value': '<?php echo csrf_token(); ?>' // hmmmm...
});
var hiddenInput =
$('<input>', {
'name': '_method',
'type': 'hidden',
'value': link.data('method')
});
return form.append(token, hiddenInput)
.appendTo('body');
}
};
laravel.initialize();
})();
@victorpierredev
Copy link

Perfect. I'm using laravel 4.2 and took me a while to realise that csrf_token has been renamed to _token, so I was getting a token mismatch. Same applies to laravel 5, but there are plenty of forks with the updated code.

As always, thanks again Jeffrey.

@raysn0w
Copy link

raysn0w commented May 16, 2015

Im curious, how did you guys managed to get this to work with the missing '$' before starting the function?

It doesnt work for me unless i add the '$'.

@8lbiasian
Copy link

how to make it work with L5 ?!

i try to change 'name': 'csrf_token', to 'name': '_token',

but i get

TokenMismatchException in VerifyCsrfToken.php line 46:

@soufianeEL
Copy link

updated to larevel 5
here

@tahertechs
Copy link

You are genious.

@jeimz143
Copy link

hi im new in larave and mine got tokenMismatch can anyone guide me on how am i suppose to include it into my tag thanks :)

@xoco70
Copy link

xoco70 commented Nov 13, 2015

I get a View [places.show] not found.

I understand it, but don't know how to fix it.
In my routes, I use resource();
So, in my route list I have GET (route/{id}) --> Show
So, I don't understand well how should have 2 identical route for 2 actions ( GET (route/{id}) to show or delete)

Here are my route list

PUT | places/{places} | places.update | App\Http\Controllers\PlaceController@update | auth,auth |
| | PATCH | places/{places} | | App\Http\Controllers\PlaceController@update | auth,auth |
| | GET|HEAD | places/{places} | places.show | App\Http\Controllers\PlaceController@show | auth,auth |
| | DELETE | places/{places} | places.destroy | App\Http\Controllers\PlaceController@destroy | auth,auth |
| | GET|HEAD | places/{places}/edit | places.edit | App\Http\Controllers\PlaceController@edit | auth,auth |

@janzenz
Copy link

janzenz commented Jan 20, 2016

Got a problem with this where the link gets redirected instead of triggering the event. So I transferred e.preventDefault(); at the beginning of handleMethod method and it solved my problem.

@Chalkin
Copy link

Chalkin commented Feb 1, 2016

Thanks a lot guys! Works perfectly and saves lives!

@junkystu
Copy link

Something like this maybe?

<meta name="_token" content="{{ csrf_token() }}">

and then send it in the form:

 'value': $('meta[name="_token"]').attr('content')

@dialyy
Copy link

dialyy commented Apr 6, 2016

Folks using L5

Line 57 to 62
change ->

      var token = 
      $('<input>', {
        'type': 'hidden',
        'name': 'csrf_token',
          'value': '<?php echo csrf_token(); ?>' // hmmmm...
        });

to ->

      $('<input>', {
        'type': 'hidden',
        'name': '_token',
          'value': link.data('token')
        }); 

@alimranahmed
Copy link

^^
Thanks @dialyy

@neoplomero
Copy link

@dialyy +1

@pastullo
Copy link

pastullo commented Jul 3, 2016

unbelievable! How crazy is that i need to paste 80 custom lines of Javascript to simply get a non-GET link to work?

Missing the super useful Rails helpers and the magic UJS:

link_to path, 'Delete', method: :delete

@MevlutOzdemir
Copy link

Thanks @dialyy !!!

Copy link

ghost commented Oct 8, 2016

Thx @Dially

@jeffochoa
Copy link

How can you test this links on laravel ?

testSomeLink() { $this->visit('link')->see('result'); }

In this case I get a method not allowed exception.

Ideas ?

@act360
Copy link

act360 commented Apr 19, 2017

I tried to modify alert layout with other js library but when i click delete it does not wait for confirm to delete.can anybody give some idea on this?

@tmomin
Copy link

tmomin commented May 16, 2017

Cant seem to get this to work.

@extends('layouts.app')

@section('title', 'Search')

@section('content')
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="/js/laravel.js"></script>

    <div class="container theme-showcase" role="main">

        <!-- Main jumbotron for a primary marketing message or call to action -->
        <div class="jumbotron">
            <h1>Welcome to AKF Golf 2017</h1>
            <p>This site is to be used to check players on the of the tournament.</p>
        </div>

        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <table class="table table-striped table-hover">
                    <thead>
                    <tr>
                        <th>#</th>
                        <th>Name</th>
                        <th>Dollar Amount</th>
                        <th>Number of Players</th>
                        <th></th>
                        <th></th>
                    </tr>
                    </thead>
                    <tbody>
                    @foreach($sponsors as $sponsor)
                        <tr>
                            <td>{{ $sponsor->id }}</td>
                            <td>{{ $sponsor->name }}</td>
                            <td>${{ $sponsor->dollarAmount }}</td>
                            <td>{{ $sponsor->numOfPlayers }}</td>
                            <td><a href="{{ url('/sponsors', [$sponsor->id]) }}">Edit</a></td>
                            <td><a href="{{ url('/sponsors', [$sponsor->id]) }}" data-method="DELETE" data-confirm="Are you sure?">Delete</a></td>
                        </tr>
                    @endforeach
                    </tbody>
                </table>
            </div>
        </div>

    </div> <!-- /container -->

@endsection

<script src="https://cdnjs.cloudflare.com/ajax/libs/signature_pad/1.5.3/signature_pad.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

@antoniputra
Copy link

I've made Javascript Vanilla version of this: https://gist.github.com/antoniputra/410af23ecc59b77d69dab0b2530718a1

no longer depend on jQuery anymore 😄

@kohlerdominik
Copy link

kohlerdominik commented Jan 22, 2018

This is a nice way for links. But for forms, in my opinion it's better to change the form attributes (and the "_method"-field if necessary). I couldn't find any solution for this, so i made my own script. It's built very like Jeffreys code.

Examples:

<input type="submit" value="Submit to alternative action" data-submit-action="/new-target">
<input type="submit" value="Submit to alternative target" data-submit-target="_blank">
<input type="submit" value="Submit as delete" data-submit-method="delete">
<input type="submit" value="Submit with confirmation" data-submit-confirmation="Are you sure?">
 {{ Form::submit('Submit alternative', [   'data-submit-action' => '/new-target',
                                        'data-submit-target' => '_blank',
                                        'data-submit-method' => 'delete',
                                        'data-submit-confirmation => 'Are you sure?'  ]); }}

I uploaded the full script to my own gist: https://gist.github.com/kohlerdominik/af78ecaec7a83e566e6fe8170f5f11bd

@hakankozakli
Copy link

If the event is not firing it is probably because document is not ready yet. Try this: https://gist.github.com/hakankozakli/3b76daa8cb49193f366178b98b64b71d

@a1iraxa
Copy link

a1iraxa commented Jul 4, 2018

This would even work in bootstrap-modal and dynamic inserted button.

https://github.com/a1iraxa/restful-delete-object

Return response must be:

{
    "success":true,
    "hide":false,
    "reload":false,
    "remove":false,
    "message":"Deleted!"
} 

Inspired by:
https://gist.github.com/dirkpostma/5442850

@nickdavies791
Copy link

How would I then send any data that is outside of the form to the form, if the form is appended to the body?

i.e. I have multiple checkboxes in a table. How would these get sent to the form so they can be deleted?

@kevinruscoe
Copy link

Here's a Vue version - https://gist.github.com/kevdotbadger/7dfd81d51c975156b50a717908cba891

turn your <a href="MY_PUT_URL" class="button">Go!</a> into <method-link href="MY_PUT_URL" method="PUT" classes="button">Go!</method-link>

@eemr3
Copy link

eemr3 commented May 18, 2020

Nice one Jeffrey, Thanks!

@rodrigoespinozadev
Copy link

rodrigoespinozadev commented Aug 1, 2020

Thank you @JeffreyWay just what i needed you rock!

@guilhermemuller
Copy link

Here's a simple update that uses vanilla JS and a default confirmation message: https://gist.github.com/guilhermemuller/114064dfe4e8ee49c37cce6f1a824081

@atulmahankal
Copy link

atulmahankal commented Oct 5, 2022

add <meta name="csrf-token" content="{{ csrf_token() }}" /> into head
then
Change below code

        'name': 'csrf_token',
        'value': '<?php echo csrf_token(); ?>' // hmmmm...

into

        'name': '_token',
	'value': document.getElementsByName('_token')[0].value,

else it gives 419 | PAGE EXPIRED Error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment