Halnex Halnex - 6 months ago 170
jQuery Question

Inline editing with Laravel 5 and Bootstrap Editable: 405 Method Not Allowed

I have a comment form and list on each post in my app, I just imported Bootstrap Editable to be able to give the users access to edit their comments inline without page reload.

But I keep getting this error


MethodNotAllowedHttpException in RouteCollection.php line 219:

POST http://localhost/r2/public/posts/comment/update 405 (Method Not Allowed)


I'm assuming it's something to do with my comment routes but I can't figure out what.

EDIT: After adding
type: 'post'
to
ajaxOptions
I started getting a different error


Creating default object from empty value


It seems like
Input::get('commenter_comment')
is not returning anything. I guess this is wrong anyway as this is not the X-Editable field that is appearing.

How can I grab the X-Editable field?

Routes

Route::get('{post}/comment', ['as' => 'comment', 'uses' => 'CommentController@index']);
Route::post('{post}/post_this_comment', 'CommentController@post_this_comment');
Route::get('{post}/recaptcha', 'CommentController@recaptcha');
Route::get('{post}/reply_comment', 'CommentController@reply_comment');
Route::post('{post}/per_page', 'CommentController@per_page');
Route::post('{post}/comment/update', 'CommentController@update');


Update()
method in
CommentController


public function update() {
$commentId = Input::get('pk');

$newComment = Input::get('commenter_comment');

$commentData = Comment::whereId($commentId)->first();

$commentData->comment = $newComment;

if($commentData->save())
return Response::json(array('status'=>1));
else
return Response::json(array('status'=>0));
}


The View

<script type="text/javascript">
$(document).ready(
function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});

$('.testedit').editable({
validate: function(value) {
if($.trim(value) == '')
return 'Value is required.';
},
type: 'textarea',
url: 'comment',
title: 'Edit Comment',
placement: 'top',
send:'always',
ajaxOptions: {
dataType: 'json'
}
});
}
);
</script>

<p><a href="#" class="testedit" pk="{{ $each_comment->id }}">{!! $each_comment->comment !!}</a></p>

Answer

As I mentioned, MethodNotAllowedHttpException is thrown when you are using different HTTP verb. I mean, in you routes you declare the update route with post verb:

Route::post('{post}/comment/update', 'CommentController@update');

However, in you ajax options when type is not defined it do the request in GET, so you must to define it:

ajaxOptions: type: 'post'

Now, another error comes. You are not passing the post id expected in route's definition, that's why you are receiving an empty id, in consequence, a empty object is returned from database. So, you must to pass it as. But first, lets change the markup a little bit for each comment in order to set the the post's url via data-url and pk via data-pk attributes:

<a 
href="#" 
class="testedit" 
data-pk="{{ $each_comment->id }}"
data-url="{!! url($post->id . '/comment/update') !!}">
    {!! $each_comment->comment !!}
</a>

Now, x-editable will catch the url and pk values automatically without be set explicitly. Your final code should be close like this:

$(document).ready(
        function(){
            $.ajaxSetup({
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                }
            });

            $('.testedit').editable({
                validate: function(value) {
                    if($.trim(value) == '')
                        return 'Value is required.';
                },
                type: 'textarea',
                title: 'Edit Comment',
                placement: 'top',
                send:'always',
                ajaxOptions: {
                    dataType: 'json',
                    type: 'post'
                }
            });
        }
    );

Don't forget that every argument defined in routes could be injected in controller's function. For example, your route is defining a {post} that expected to be the post id to edit:

Route::post('{post}/comment/update', 'CommentController@update'); 

So, in your update() just inject the argument:

public function update(Request $request, $post) {
    //$post has the Id of post to be edited

    // catching pk id:
    $pk = $request->get('pk');

    // catching the new comment
    $comment = $request->get('value');
Comments