I'm writing a Laravel app and trying to implement a modal showing some details on an element. When I'm clicking on the link the backdrop is showing but not the modal window. In the network monitor of chrome it is showing the modal window in preview.
What's wrong?
Thank you in advance for your help!
Here is my code
index.blade.php
<td>
Details
</td>
modal.blade.php
<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>
show.blade.php
#extends('layouts.modal')
#section('title')
Demo Modal
#endsection
#section('content')
<p>test</p>
#endsection
#section('footer')
<button type="button" data-dismiss="modal">Close</button>
#endsection
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');
});
ProjectController.php
public function show($id)
{
$project = Project::findOrFail($id);
return view('projects.show', compact('project'));
}
Hey never use HTML Element in making a clickable modals that has value on it.
I suggest you used add value on it , That can be "ID" then add modal attributes on it, Then boom everything is fine and working.
You need to specify the html id tag in your link.
I suggest you try this
<a data-toggle="modal" id="smallButton" data-target="#smallModal"
data-attr="{{ route('projects.show', $project->id) }}" title="show">
<i class="fas fa-eye text-success fa-lg"></i>
</a>
<!-- small modal -->
<div class="modal fade" id="smallModal" tabindex="-1" role="dialog" aria-labelledby="smallModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-sm" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="smallBody">
<div>
<!-- the result to be displayed apply here -->
</div>
</div>
</div>
</div>
</div>
<script>
// display a modal (small modal)
$(document).on('click', '#smallButton', function(event) {
event.preventDefault();
let href = $(this).attr('data-attr');
$.ajax({
url: href,
beforeSend: function() {
$('#loader').show();
},
// return the result
success: function(result) {
$('#smallModal').modal("show");
$('#smallBody').html(result).show();
},
complete: function() {
$('#loader').hide();
},
error: function(jqXHR, testStatus, error) {
console.log(error);
alert("Page " + href + " cannot open. Error:" + error);
$('#loader').hide();
},
timeout: 8000
})
});
</script>
In your Remote.js file :
$(document).on('ajax:success', function(e, xhr){
if(!$('#modal').length){
$('body').append($('<div class="modal" id="modal"></div>'))
}
$('#modal').modal('show');
$('#modal').html(xhr.responseText);
});
Related
I want to open a modal with information about the offer that is grabbed from the database.
Here's what I have so far: (Minimal required code)
Opening modal:
<a href="" data-bs-toggle="modal" data-bs-target="#infoPonuka">
<i class="fa-solid fa-eye spc"> </i>
</a>
Modal:
<div class="modal fade" id="infoPonuka" tabindex="-1" aria-labelledby="infoPonuka" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="infoPonuka">Ponuka - info:</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
#if(isset($_GET['id']))
#foreach ($ponuky AS $item)
#if($item->ID == $_GET['id'])
#php
$ponuka = $item;
#endphp
{{Debug::printr($ponuka, false);}}
#endif
#endforeach
#endif
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Zatvoriť</button>
</div>
</div>
</div>
</div>
When I was doing it, I thought I could maybe just use $_GET to get the ID of the offer, so I can have specific data from an array because every opening modal (the first code block) is shown on every item, so I wanted to make it unique for every button by maybe adding the href="?id={{ $ponuka->ID }}". But I was unable to do so. Does someone have any idea?
You might use ajax request on click of your anchor tag instead of using these attributes data-bs-toggle="modal" data-bs-target="#infoPonuka", and then, in response of your ajax request, set the data in the html of the modal as Passing ajax response data to modal
and then show the modal as:
$("#modalId").modal("show");
right after the line your data is set to modal html.
Make a method in a Controller and a route:
This will retun a redered view.
public function getOffer($offer_id)
{
$offer = Offer::where('id', $offer_id);
$renderedOfferView = view('modal.offer', ['offer' => $offer)->render();
return return response()->json(['status' => 'success', 'renderedOfferView' => $renderedOfferView]);
}
In your blade:
<a href="" data-bs-toggle="modal" data-bs-target="#infoPonuka" onclick="getOffer('{{ $ponuka->ID }}')">
<i class="fa-solid fa-eye spc"> </i>
</a>
<div class="modal fade" id="infoPonuka" tabindex="-1" aria-labelledby="infoPonuka" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="infoPonuka">Ponuka - info:</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="getOfferContent">
<!-- use the getOfferContent id to fill with data -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Zatvoriť</button>
</div>
</div>
</div>
</div>
getOffer(id){
$('#getOfferContent').html(''); // clear data
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: '/your-getOffer-route',
type: 'GET',
data: {
id: id,
},
success: function( response ) {
$('#getOfferContent').html(response.renderedOfferView); // fill data
},
error: function( response ) {
}
});
}
Do not forgot to set: <meta name="csrf-token" content="{{ csrf_token() }}"> in your layout.blade.php into <head> tag
I am using bootstrap modal to show to data which is fetched from the database. I have this code for load remote PHP data into bootstrap modal. it is work. but i need to add a loading message into the modal until data fetch from database. I have this code for load remote PHP data into bootstrap modal box
index.html
<script>
$(document).ready(function(){
$('#myModal').on('show.bs.modal', function (e) {
var rowid = $(e.relatedTarget).data('id');
$.ajax({
type : 'post',
url : 'fetch_subjects.php', //Here you will fetch records
data : 'rowid='+ rowid, //Pass $id
success : function(data){
$('.fetched-data').html(data);//Show fetched data from database
}
});
});
});
</script>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Subjects</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="fetched-data"> </div> <!--fetched dates here -->
</div>
<div class="modal-footer">
<button type="butZton" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
fetch_subjects.php
<?php
require 'db_connection.php';
if($_POST['rowid']) {
$id = $_POST['rowid'];
$sql = "SELECT * FROM subject where year=$id";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "<div class='list-group'>
<b>
<a href='notes?id=". $row['id'] ."' class='list-group-item list-group-item-action' target='_blank'>
" . $row["name"]. "
</a>
</b>
</div>
</button>";
}
}
else {
echo "no details.";
}
}
?>
I would do that this way:
$.ajax({
type : 'post',
url : 'fetch_subjects.php', //Here you will fetch records
data : 'rowid='+ rowid, //Pass $id
success : function(data){
$('.fetched-data').html(data);//Show fetched data from database
},
beforeSend: function() {
$('#loader').show(); // Assuming that you have some loader defined
},
complete: function(){
$('#loader').hide(); //Hide this loader
},
});
<script>
$(document).ready(function(){
$('#myModal').on('show.bs.modal', function (e) {
var rowid = $(e.relatedTarget).data('id');
$.ajax({
type : 'post',
url : 'fetch_subjects.php', //Here you will fetch records
data : 'rowid='+ rowid, //Pass $id
beforeSend: function() {
$('.loader').show(); // Assuming that you have some loader defined
},
success : function(data){
$('.fetched-data').html(data);//Show fetched data from database
$('.loader').hide();
},
});
});
});
</script>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Subjects</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- loader -->
<div class="loader">
loading.............
</div>
<div class="fetched-data"> </div> <!--fetched dates here -->
</div>
<div class="modal-footer">
<button type="butZton" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Below is my main blade file that I want to load into modal.
#extends('layouts.app')
#section('title', trans('pages.jobs.show.header_title') ?: trans('pages.jobs.show.title'))
#section('navigation')
#endsection
#section('content')
<div class="container">
<div class="page-dashboard">
{{ all teh content loaded: such as SVG grapgh using JS }}
</div>
</div>
<nav class="container-fluid nav-bottom" data-js="nav-bottom">
<div class="nav-bottom__overlay"></div>
</nav>
#push('scripts')
<script src=""></script>
#endpush
#endsection
I have tried using bootstarp.js modal but the modal is not loading, it loads in the main page.
Is it possible to load an entire blade with its own CSS and js included?
Kindly provide me any example. Maybe, I have to use ajax:
$('#modellink').click(function(){
$.ajax({
type : 'GET',
url : $(this).data('path'),
success: function(result, url) {
$('.modal-body').html(result);
$('#myModal').modal('show');
$('.modal-container').load($(this).data('path'),function(result){
$('#myModal').modal({show:true});
});
}
});
});
If you have a file call modal.blade.php, which has all the HTML, CSS and JS for that modal, you can include it on any page with #include("modal"). For example:
modal.blade.php
<style>...</style>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">...</script>
Then, in your main file:
main.blade.php
#extends("layout")
#section("content")
#include("modal")
<div>...</div>
Return the HTML string
// SomeController::getModal()
return view('layouts.someview', $data_array)->render();
Load it into the modal
$.ajax(
// blah,
// blah,
success: function(response) {
$('#modal').html(response)
}
)
In short - yes.
Im not sure how you're loading your modal - as you don't provide much information, but, if you can load an external page into your modal, then simply point to the laravel route that displays your blade view.
Alternatively, use an #include('modal.name.blade') and have that as part of the page which uses the modal with the correct html/css of course for your relevant modal script.
I want to edit record in cakephp for that i want to load modal popup that is placed inside another view edit.ctp. There is a page view.ctp where user can click link on a link and modal popup will show up. I need a different view for my modalpopup. Below is code.Please help to solve my issue. If i place my modal on the same page i.e. view.ctp it is working but i need a different view.
view.ctp
<li>
<?php
echo $this->Html->link("Edit Profucts","/PanelAdmin/products/edit/".$prod->product_id, array('update' => '#flexModal','id'=>'flexModal','data-target' => 'flexModal','htmlAttributes' => array('data-toggle' => 'modal',)));
?>
</li>
<script>
$(document).ready(function() {
$("a[data-target='flexModal']").click(function(ev) {
ev.preventDefault();
var target = $('#flexModal').attr("href");
$("#flexModals .modal-body").load(target, function(data) {
$("#flexModals").modal("show");
});
});
});
</script>
edit.ctp
<div class="modal" data-target="#flexModal" tabindex="-1" role="dialog" data-backdrop="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title" id="myModalLabel"></h3>
</div>
<div class="modal-body">
<?php
echo $products->product_name;
echo $products->product_desc;
?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
ProductsController.php
public function edit($id)
{
$products = $this->Products->get($id);
$this->set(compact('products'));
}
Currently I'm using Laravel 5.2 with Elixir 5 and Vue 2.0.
I'm stuck on how to access and imported component's data from the element view using something like v-if.
Here's my setup:
resources\views\vuetest.blade.php
<div id="app">
<modal v-if="showModal"></modal>
<button>Show Modal</button>
</div>
resources\assets\vuejs\app.js
import Vue from 'vue';
import Modal from './components/modals/show-modal.vue';
Vue.component('modal', Modal);
if (document.getElementById("app")){
var app = new Vue({
el: '#app',
data: {
},
methods: {
},
computed: {
},
components: {
'modal': Modal
}
});
window.vue = app;
}
resources\assets\vuejs\components\modals\show-modal.vue
<template>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showModal: false
}
},
components: {
},
}
</script>
Now if I just use this without v-if then it works and pulls in the template correctly.
However if I use what I had in my example it gives me an error:
app.js:967 [Vue warn]: Property or method "showModal" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in <Root>)
If I add data in main app.js it can access it but not in imported child components. I'd rather not make the main app.js messy and better to use imports and keep components in organized subfolders. How can I access these child component data properly?
If you want to change the state of the child component, you can set a ref on the component and access the properties directly.
In this example, a ref is set on each modal component.
<bootstrap-modal ref="modal1">
Then, to change a data value in the referenced component, simply set it like you would any other javascript value.
<button type="button" class="btn btn-primary" #click="$refs.modal1.visible = true">Show Modal One</button>
console.clear()
const BootstrapModal = {
template: "#modal-template",
data() {
return {
visible: false
}
},
watch: {
visible(show) {
if (show) $(this.$el).modal('show')
else $(this.$el).modal('hide')
}
},
mounted() {
// listen for the close event
$(this.$el).on("hidden.bs.modal", () => {
this.visible = false
})
}
}
new Vue({
el: "#app",
components: {
BootstrapModal
}
})
<script src="https://unpkg.com/vue#2.4.2"></script>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<div id="app">
<button type="button" class="btn btn-primary" #click="$refs.modal1.visible = true">Show Modal One</button>
<bootstrap-modal ref="modal1">
<span slot="title">Modal One</span>
<p slot="body">Modal One Content</p>
</bootstrap-modal>
<button type="button" class="btn btn-success" #click="$refs.modal2.visible = true">Show Modal Two</button>
<bootstrap-modal ref="modal2">
<span slot="title">Modal Two</span>
<p slot="body">Modal Two Content</p>
</bootstrap-modal>
</div>
<template id="modal-template">
<div class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><slot name="title">Modal Title</slot></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<slot name="body"><p>Modal Body</p></slot>
</div>
<div class="modal-footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</div>
</template>
You need to declare the var showModal on your main app.
data: {
showModal: false
},
You also need to toggle that variable everytime they click the button, so add this to your button:
<button #click="showModal = !showModal">Show Modal</button>
Also i suggest to wrap your modal inside template with a div. Since vuejs required this.
<template>
<div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</template>
Short answer: you are trying to access property of child component within the scope of parent component (or, the Root instance in your case). You should declare showModal property on the Parent component instead.
var app = new Vue({
el: '#app',
components: {Modal},
data: {
showModal: false
},
});
and then you would have the button changing the state of your property:
<button #click="showModal = true"></button>
The tricky part is close out the modal - because you can't reach your button anymore when the modal is active. You would have to change the state of your parent component from your child component. You can use custom events in this case, like so:
In the show-modal.vue
<div class="modal-footer">
<button type="button" class="btn btn-default" #click="close">
Close
</button>
</div>
...
<script>
export default {
methods: {
close() {
this.$emit('close');
}
}
}
And now, all we have to do is to listen on that custom event we just fired in the main template, like so;
<modal v-if="showModal" #close="showModal = false"></modal>
Not sure if best way but I figured it out with the help from this:
VueJS access child component's data from parent
What I did was in my child component I put the following:
<template>
<div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
showModal: false
}
},
components: {
},
}
</script>
Then in my vuetest.blade.php I put this:
<div id="app">
<modal v-if="modalData.showModal"></modal>
<button>Show Modal</button>
</div>
Then lastly in my app.js I did this:
import Vue from 'vue';
import Modal from './components/modals/show-modal.vue';
if (document.getElementById("app")){
var app = new Vue({
el: '#app',
data: {
modalData: Modal.data()
},
methods: {
},
computed: {
},
components: {
'modal': Modal
}
});
window.vue = app;
}
I didn't complete the code for the show modal button obviously but at least using this way I can now access child data. I would just need to define this for every component which should account for as many vars it contains inside the data.
Also thanks Carlos for suggestion of wrapping it into a div.