Laravel on Modals
Or How I Learned to Stop Worrying and Love the Modals. Part 1.
TL;DR: How to work with Modals (e.g. Bootstrap) on Laravel just like with Blade Templates, including Server-side Form Validation, rendering errors, redirects, etc.
Once, I was looking for a good PHP framework, that would be as great as RubyOnRails which was ¡Numero Uno! for me back then, or how Yukihiro Matsumoto would say: “一番”. So I’ve found one. Yes, your favorite one. I’m still missing for a ton of great stuff from RoR, but few great things could be easily brought in this Laravorld. So, one of them is…
jquery-ujs
There are not many articles on how to set up and use Laravel and jquery-usj. Except for this one, which is a good place to start to realize the purpose of it:
Installation jquery-ujs on Laravel
I’m sure you know the drill, so let’s skip Laravel installation. First, install the package by npm with other default packages (e.g. jquery) by commands:
npm install
npm install --save jquery-ujs
and add it to the project, as I do in resources/js/app.js
require('jquery-ujs');
Usage jquery-ujs for Modals in Laravel
On RoR, I was also using jquery-ujs in ways as described in the post above. But especially for the Modals, where Modals became as easy as Blade Layouts. With Validation! And (almost) without JS!
Set up JS part and Modal Layout
Create remote.js and add it to the resources/js/app.js somewhere at the end.
// resources/js/app.jsrequire('./bootstrap');
require('jquery-ujs');
require('./remote');
// resources/js/remote.js$(document).on('ajax:success', function(e, xhr){
if(!$('#modal').length){
$('body').append($('<div class="modal" id="modal"></div>'))
}
$('#modal').html(xhr.responseText).modal('show');
});
As you see, we just put AJAX response to the #modal element and show it. Don’t forget to run npm run dev
on the root of the project to compile new public/js/app.js and check if you have a good Mix of it.
NOTICE! (Update 06.04.2020)
In the example above I receive Modal's HTML from XHR as xhr.responseText
But some devs report that it doesn't work for them,
and xhr property already contains HTML, instead of object.
Please check what do you receive in xhr by logging first:
console.log(xhr);
Let’s make a new Modal Layout resources/views/layouts/modal.blade.php And we are ready to pop up Modals all over the site!
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">@yield('title')</h5>
</div>
<div class="modal-body">@yield('content')</div>
<div class="modal-footer">@yield('footer')</div>
</div>
</div>// Keep in mind there's no <div class="modal" id="modal"></div>
Usage of Modal Layout
To show the View in Modal Layout, extend it as you extend any other layout.
// Example of Create Post Form on Modal Layout in
// resources/views/posts/create.blade.php
// 'layout.errors' simple template to show validation errors.@extends('layouts.modal')@section('title') Demo Modal @endsection@section('content')<form action="/store" method="POST" data-remote="true">
@csrf
@include('layouts.errors')
<input type="email" name="email" class="form-control">
<input type="name" name="name" class="form-control">
<button type="submit" class="btn btn-primary">Close</button>
</form>@endsection@section('footer')
<button type="button" data-dismiss="modal">Close</button>
@endsection
And Render it in a Controller as you usually do in the Controller.
public function create()
{
return view('posts.create');
}
To show the Modal, use a simple link to the data-remote="true"
<a href="/posts/create" data-remote="true"> Create Post </a>
<a href="/posts/1/edit" data-remote="true"> Edit Post</a><a href="/posts/1" data-remote="true"> Show Post </a>
What I usually do with simple Modals, is Delete confirmations. For example:
// App\Http\PostController.php...
public function destroy(Request $request, Post $post)
{
if($request->ajax()){
return view('posts.destroy', compact('post'));
}else{
$post->delete();
return redirect()->route('posts.index');
}
}// ... some link anywhere
<a href="{{ route('posts.destroy') }}" data-remote="true"
data-method="DELETE">
Delete
</a>
And You right, views/posts/desrtoy.blade.php shows a regular form with a question “Do you really want to delete: {{ $post->name }}?”… you get it.
In the next post, I’ll tell you how to implement Form Validation on Modals in Laravel, just like a regular one, without JS, redirects and so on. see yah…