anndexi99
anndexi99

Reputation: 199

Laravel delete form button in modal goes outside of form element and doesn't delete item

I am working on the CRUD part of a Laravel app.

It is supposed that when the delete button of an entry is clicked, a modal show up and ask user to confirm delete the corresponding entry or not.

This is my frontend code.

My plan A:

You can see the confirm button in the modal is inside the form in the code but it went outside the form element in the actual HTML document.

The button which make the modal visible when clicked

<button id="pj_btn_delete-{{ $project->id }}" 
   class="btn btn-danger pj_btn_delete" type="button" 
   data-toggle="modal" data-target="#pj_modal_delete-{{ $project->id }}">
   Delete</button>

The delete modal in blade

<div id="pj_modal_delete-{{ $project->id }}" class="modal fade pj_modal_delete"
            tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
            <div class="modal-dialog modal-lg" role="document">
                <div class="modal-header">
                  <button type="button" class="close" data-dismiss="modal">&times;</button>
                  <h4 class="modal-title">X</h4>
                </div>
                <div class="modal-body">
                  <p>Are you sure to delete it?</p>
                </div>
                <div class="modal-footer">
                        <button type="button" id="pj_cancel-{{ $project->id }}" class="btn btn-default pj_cancel" data-dismiss="modal">Cancel</button>
                        <form id="pj_form_delete-{{ $project->id }}"
                            action="{{ route('projects.destroy',$project->id) }}" method="POST">
                            @csrf
                            @method('DELETE')
                            <button type="submit" id="pj_delete-{{ $project->id }}"
                                class="btn btn-primary pj_delete">Confirm
                            </button>
                        </form>
                </div>
              </div>
            </div>
        </div>

Btw, these are the code of routing and controller

the routes

Route::resource('admin/projects','ProjectController');

the delete method in controller

 public function destroy(Project $project)
{
    $project->clients()->detach();
    $project->staff()->detach();
    // $project->slack_channels()->detach();
    $project->delete();

    return redirect()->route('projects.index')
                    ->with('success','The deletion is complete');
}

My plan B:

I have also tried to submit the delete form by JS like this but it didn't change anything.

$( ".pj_delete" ).click(function() {

    let pj_id = $(this).attr('id').split('-')[1];
    let pj_form_delete_id = "pj_form_delete-" + pj_id;

    $(pj_form_delete_id).submit();

});

My plan C:

I also turned the confirm button of the modal into a link to the delete method. Also didn't work.

<a class="btn btn-primary" href="{{ 
 route('projects.destroy',$project->id) }}">Confirm</a>

the plan C delete route

Route::delete('admin/project/delete/{id}',array('uses' => 'ProjectController@destroy', 'as' => 'project.delete'));

Neither of these approaches generated a confirm button that can delete the item with corresponding id and I got no error in all these approaches. Please help. Thanks!

Upvotes: 1

Views: 1626

Answers (2)

jeremykenedy
jeremykenedy

Reputation: 4285

Here is the solution I have came up with for you (It a completed plan A). Please note I left in language files calls because I figured it would come in handy:

Please let me know if you have any questions or need to see an open source project a working example.

For ease I am using this package Form Builder https://laravelcollective.com/docs/master/html#installation It is not needed but you would need to change out the calls for normal HTML forms and HTML buttons.

Best of luck!

Jeremy

// Web Admin Routes web.php

Route::group(['prefix' => 'admin'], function () {
    Route::resource('projects', 'ProjectController', [
        'names'    => [
            'destroy'   => 'destroyproject',
        ]
    ]);
});

//HTML Form Blade View File: /resources/views/admin/modals/delete-project-modal-form.php

<div class="modal fade modal-danger" id="modal_delete" role="dialog" aria-labelledby="confirmDeleteLabel" aria-hidden="true" tabindex="-1">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header bg-danger text-white">
                <h5 class="modal-title">
                    <i class="fa fa-question-circle fa-fw mr-1 text-white"></i>
                    {!! trans('admin.modals.delete-project.title') !!}
                </h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                    <span class="sr-only">
                        {!! trans('admin.modals.delete-project.close') !!}
                    </span>
                </button>
            </div>
            <div class="modal-body">
                <p>
                    {!! trans('admin.modals.delete-project.message') !!}
                </p>
            </div>
            <div class="modal-footer">
                {!! Form::open(['method' => 'DELETE', 'route' => ['destroyproject', $projectId], 'role' => 'form', 'id' => 'delete_project_form', 'name' => 'delete_project_form']) !!}
                    <input type="hidden" name="_token" value="{{ csrf_token() }}">
                    <input type="hidden" name="_method" value="DELETE">
                    <meta name="_token" content="{!! csrf_token() !!}" />
                    {!! Form::button('<i class="fa fa-fw fa-close" aria-hidden="true"></i> ' . trans('admin.modals.delete-project.cancel'), array('class' => 'btn btn-outline pull-left btn-light', 'type' => 'button', 'data-dismiss' => 'modal' )) !!}
                    {!! Form::button('<i class="fa fa-fw fa-trash-o" aria-hidden="true"></i> ' . trans('admin.modals.delete-project.confirm'), array('class' => 'btn btn-danger pull-right', 'type' => 'submit', 'id' => 'confirm' )) !!}
                {!! Form::close() !!}
            </div>
        </div>
    </div>
</div>

// Include the above modal blade from your blade

@include('admin.modals.delete-project-modal-form', ['projectId' => $project->id])

// Modal HTML Trigger in your blade

<button type="button" class="btn btn-danger btn-sm btn-block delete-project-trigger" data-toggle="modal" data-target="#modal_delete" data-projectid="{{ $project->id }}">
    <i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>
    <span class="hidden-xs hidden-sm hidden-md">
        {{ trans('admin.buttons.delete') }}
    </span>
</button>

// Javascript to include in your blade to trigger the modal

@push('scripts')
    <script type="text/javascript">
        $('.delete-project-trigger').click(function(event) {
            var projectId = $(this).data("projectid");
            $('#modal_delete').on('show.bs.modal', function (e) {
                document.delete_project_form.action = "{{ url('/') }}" + "/admin/projects/" + projectId;
            });
        });
    </script>
@endpush

// Include this in your app.blade.php or whatever layout you are using to make sure you can include the sciprts:

@stack('scripts')

// In ProjectController.php // Make sure you include the call to the project model at the top of the file something like:

use App\Models\Project;

// Here is the destroy method in ProjectController.php

/**
 * Remove the specified resource from storage.
 *
 * @param Request $request
 * @param int $id
 *
 * @return \Illuminate\Http\Response
 */
public function destroy(Request $request, $id)
{
    $project = Project::findOrFail($id);

    $project->clients()->detach();
    $project->staff()->detach();
    // $project->slack_channels()->detach();

    $project->delete();

    return redirect()
        ->route('projects.index')
        ->withSuccess(trans('messages.success.project-deleted'));
}

// The Language lines file: /resources/lang/en/admin.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Admin language lines
    |--------------------------------------------------------------------------
    |
    */

    'modals' => [
        'delete-project' => [
            'close'     => 'Close',
            'title'     => 'Confirm Delete',
            'message'   => 'Delete this project?',
            'cancel'    => 'Cancel',
            'confirm'   => 'Confirm Delete',
        ]
    ],

];

// The Language lines file: /resources/lang/en/messages.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Message language lines
    |--------------------------------------------------------------------------
    |
    */

    'success' => [
        'project-deleted' => 'Project deleted.',
    ],

];

Working file of outlined examples for reference:

Example Project 1

Routes https://github.com/jeremykenedy/larablog/blob/master/routes/web.php#L48

Controller https://github.com/jeremykenedy/larablog/blob/master/app/Http/Controllers/Admin/PostController.php#L115

Request https://github.com/jeremykenedy/larablog/blob/master/app/Http/Requests/DestroyPostRequest.php

Blade Files https://github.com/jeremykenedy/larablog/blob/master/resources/views/admin/post/edit.blade.php#L70

https://github.com/jeremykenedy/larablog/blob/master/resources/views/admin/post/edit.blade.php#L87

https://github.com/jeremykenedy/larablog/blob/master/resources/views/admin/post/edit.blade.php#L93

https://github.com/jeremykenedy/larablog/blob/master/resources/views/admin/modals/delete-modal.blade.php

Example Project 2

Routes https://github.com/jeremykenedy/laravel-users/blob/master/src/routes/web.php#L15

Controller https://github.com/jeremykenedy/laravel-users/blob/master/src/App/Http/Controllers/UsersManagementController.php#L246

Blade Files https://github.com/jeremykenedy/laravel-users/blob/master/src/resources/views/usersmanagement/show-user.blade.php#L59

https://github.com/jeremykenedy/laravel-users/blob/master/src/resources/views/usersmanagement/show-user.blade.php#L191

https://github.com/jeremykenedy/laravel-users/blob/master/src/resources/views/usersmanagement/show-user.blade.php#L195

https://github.com/jeremykenedy/laravel-users/blob/master/src/resources/views/modals/modal-delete.blade.php

https://github.com/jeremykenedy/laravel-users/blob/master/src/resources/views/scripts/delete-modal-script.blade.php

Example Project 3

Routes https://github.com/jeremykenedy/laravel-logger/blob/master/src/routes/web.php#L21

Controller https://github.com/jeremykenedy/laravel-logger/blob/master/src/app/Http/Controllers/LaravelLoggerController.php#L141

Blade Files https://github.com/jeremykenedy/laravel-logger/blob/master/src/resources/views/logger/activity-log.blade.php#L24

https://github.com/jeremykenedy/laravel-logger/blob/master/src/resources/views/logger/activity-log.blade.php#L132

https://github.com/jeremykenedy/laravel-logger/blob/master/src/resources/views/forms/delete-activity-log.blade.php

https://github.com/jeremykenedy/laravel-logger/blob/master/src/resources/views/scripts/confirm-modal.blade.php

This can be done and there are 3 live projects with it working.

Upvotes: 1

Peter
Peter

Reputation: 1725

You should indicate what the error was with your first attempt. You just say that it didn't work.

For your plan B, you need to add a # to your selector:

let pj_form_delete_id = "#pj_form_delete-" + pj_id;

... and for your plan C you need a GET route instead of DELETE to make it work with a link. A clicked link generates a GET request.

Route::get('admin/project/delete/{id}',array('uses' => 'ProjectController@destroy', 'as' => 'project.delete'));

That being said, you should try to get your first attempt using a DELETE and a form working. If you can provide more details on what didn't work someone might be able to help you.

Upvotes: 1

Related Questions