Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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();
})();

Nice one Jeffrey, Thanks!

Wonder if it would be easier to add an additional data* method for token?

<a href="posts/2" data-method="delete" data-token="{{ csrf_token() }} 
Owner

JeffreyWay commented Mar 8, 2013

Yeah, the embedded PHP is a temporary thing.

Maybe store the csrf token in a meta tag, and then just grab that value from the script. That way, the user never has to worry about passing the token custom attribute.

Yep, grab that guy from a meta tag. Otherwise 👍

Looks interesting, although I've always thought the best way around this is to define a new HTML helper function that spits out the form and button (with appropriate link styling or whatever) directly from PHP. Added bonus is that there's no bodging for the token, and non-JS people get the correct experience.

Incidentally, I've only ever seen one framework actually include this functionality for 'delete' action buttons (either using a 'proper' DELETE form or back when we just POSTed to a /delete and didn't pass a method or care about being RESTful) out of the box although can't currently remember which. Maybe Yii.

I recently created an ajax way of sending DELETE requests. I'm a jQuery newbee (getting better using your tuts, thanks again!), but I gave it a try.

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

$(document).ready(function() {

// Add click handler to restful hyperlinks,
// e.g. to send DELETE requests
// Example:
// 
// <a href="/destroy/1" class="rest-delete">delete</a>
// <script>restful.init($('.rest-delete'));</script>
// 
var restful = {

    // TODO: add various configurations, e.g.
    // - do_confirm: [ true | false ]
    // - confirm_message: "Are you sure?"
    // - do_remove_parent: [ true | false ]
    // - parent_selector: '.li' '.div' ...
    // - success: (closure)

    init: function(elem) {
        elem.on('click', function(e) {
            self=$(this);
            e.preventDefault();

            if(confirm('Are you sure?')) {
              $.ajax({
                url: self.attr('href'),
                method: 'DELETE',
                success: function(data) {
                  self.parent('li').remove(); // todo: make configurable
                },
                error: function(data) {
                    alert("Error while deleting.");
                    console.log(data);
                }
              });
            };
        })
    },
}

restful.init($('.rest-delete'));
});

Thanks!

gpai commented Apr 30, 2014

Thanks a bunch! This helped so much!

cmd0315 commented Aug 11, 2014

Hi Jeffrey! I just started using Laravel for my web app projects. Can you pls elaborate on your js script? Sorry, I am a bit confused. What link should I provide in the anchor tag? Same link as the one in the form prior to it or should I create another route that uses a different method in the controller? I am already using a form for the update process so I want the delete request to be done outside of it. Thanks.

cavalor commented Aug 23, 2014

thanks!!! that helped me so much.

dlm423 commented Sep 5, 2014

Thanks for this script, seems quite useful! I am having an issue, my <a> tag is redirecting me to another page, as opposed to submitting the DELETE request. I asked a question on Stack Overflow and hope to get some help in case anyone else runs into this issue. http://stackoverflow.com/questions/25695137/delete-request-outside-of-form-laravel/25695164

I don't know why I cannot implement this function. I use Debugbar and it displayed the error: View [posts.record] not found. Any idea?

roNn23 commented Feb 12, 2015

Updated the script for Laravel 5 (the token-input was renamed to _token):
https://gist.github.com/roNn23/a86f31ecaf0c6e0a7d65

Thanks, work like charm. You are the best Jeffrey :)

What would be the be the best way to style the dialog/popup like a JQuery dialog/modal, with the script in laravel.js? I'm more of a back-end developer, so my Javascript knowledge needs improving...

vpakg commented May 14, 2015

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 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 '$'.

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:

updated to larevel 5
here

You are genious.

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 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 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 commented Feb 1, 2016

Thanks a lot guys! Works perfectly and saves lives!

Something like this maybe?

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

and then send it in the form:

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

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')
        }); 

^^
Thanks @dialyy

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

Thanks @dialyy !!!

Thx @dially

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 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 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>

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

no longer depend on jQuery anymore 😄

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