Laravel 5.1 and DropzoneJS 4.2 can‘t upload photo - laravel

I am using Laravel 5.1 and DropzoneJS 4.2 to upload images,I copied the code of this example http://www.dropzonejs.com/bootstrap.html,and modified it.
click the start button,can not send http request.
This is my wiew:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css">
<style>
html, body {
height: 100%;
}
#actions {
margin: 2em 0;
}
/* Mimic table appearance */
div.table {
display: table;
}
div.table .file-row {
display: table-row;
}
div.table .file-row > div {
display: table-cell;
vertical-align: top;
border-top: 1px solid #ddd;
padding: 8px;
}
div.table .file-row:nth-child(odd) {
background: #f9f9f9;
}
/* The total progress gets shown by event listeners */
#total-progress {
opacity: 0;
transition: opacity 0.3s linear;
}
/* Hide the progress bar when finished */
#previews .file-row.dz-success .progress {
opacity: 0;
transition: opacity 0.3s linear;
}
/* Hide the delete button initially */
#previews .file-row .delete {
display: none;
}
/* Hide the start and cancel buttons and show the delete button */
#previews .file-row.dz-success .start,
#previews .file-row.dz-success .cancel {
display: none;
}
#previews .file-row.dz-success .delete {
display: block;
}
</style>
</head>
<body>
<div class="container" id="container">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
upload photos
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog dropzone" id="my-awesome-dropzone" 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>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="myModalLabel">upload photos</h4>
</div>
<div class="modal-body">
<div id="actions" class="row">
<div class="col-lg-7">
<span class="btn btn-success fileinput-button dz-clickable">
<i class="glyphicon glyphicon-plus"></i>
<span>add photos</span>
</span>
</div>
</div>
<div class="table table-striped files" id="previews">
<div id="template" class="file-row">
<!-- This is used as the file preview template -->
<div><span class="preview"><img data-dz-thumbnail/></span></div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar"
aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;"
data-dz-uploadprogress></div>
</div>
</div>
<div>
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<script src="http://ajax.useso.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<script src="https://cdn.bootcss.com/dropzone/4.2.0/min/dropzone.min.js"></script>
</body>
</html>
This is the script:
<script>
Dropzone.autoDiscover = false;
</script>
<script>
// Get the template HTML and remove it from the doument
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.body, { // Make the whole body a dropzone
url: "fileupload", // Set the url
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: "#previews", // Define the container to display the previews
clickable: ".fileinput-button" // Define the element that should be used as click trigger to select files.
});
myDropzone.on("addedfile", function (file) {
// Hookup the start button
file.previewElement.querySelector(".start").onclick = function () {
myDropzone.enqueueFile(file);
};
});
// Update the total progress bar
myDropzone.on("totaluploadprogress", function (progress) {
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on("sending", function (file) {
// Show the total progress bar when upload starts
document.querySelector("#total-progress").style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone.on("queuecomplete", function (progress) {
document.querySelector("#total-progress").style.opacity = "0";
});
// Setup the buttons for all transfers
// The "add files" button doesn't need to be setup because the config
// `clickable` has already been specified.
document.querySelector("#actions .start").onclick = function () {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function () {
myDropzone.removeAllFiles(true);
};
</script>
This is the route:
Route::resource('fileupload', 'FileController');
These is the controller:
public function imageUpload(Requests\StorePhotoPostRequest $request)
{
$this->wrongTokenAjax();
$file = \Input::file('file');
$destinationPath = 'uploads/';
$extension = $file->getClientOriginalExtension();
$fileName = \Auth::user()->id . '_' . time() . '.' . $extension;
$upload_success = \Input::file('file')->move($destinationPath, $fileName);
if ($upload_success) {
return \Response::json('success', 200);
} else {
return \Response::json('error', 400);
}
}
public function wrongTokenAjax()
{
if (\Session::token() !== \Request::get('_token')) {
$response = [
'status' => false,
'errors' => 'Wrong Token',
];
return \Response::json($response);
}
}
This is the request:
public function rules()
{
return [
'file' => 'required|image(jpeg,jpg,png,bmp,gif)',
];
}

I think the problem is that you don't send the CSRF Token with the upload.
First of all add the CSRF Token in the <head>:
<meta name="csrf_token" content="{{ csrf_token() }}">
Try to replace this
myDropzone.on("sending", function (file) {
// Show the total progress bar when upload starts
document.querySelector("#total-progress").style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
With this:
myDropzone.on("sending", function (file, xhr, formData) {
formData.append("_token", $('[name="csrf_token"]').attr('content'));
});

Related

laravel livewire refresh when updating variable

As you can see I am trying to make a list of categories, using ul/li on laravel livewire, the problem is that when I click on the "+" it transform to "-" as expected but retransform to "+", because I think DOM reloads.
controller:
<?php
namespace App\Http\Livewire\Product;
use App\Classes\Product\ShopifyCatList;
use Livewire\Component;
class ShopifyNewCategory extends Component
{
public $categories, $html;
private function getFirstCat()
{
$shopifyCatList = new ShopifyCatList();
$this->categories = $shopifyCatList->getFirstCat();
}
public function addChildren($rank)
{
$shopifyCatList = new ShopifyCatList();
$this->categories = $shopifyCatList->updateCategories($rank);
$this->html = $shopifyCatList->updateHtml($this->html, $this->categories, $rank);
}
public function mount()
{
$this->getFirstCat();
$this->html = '<li data-rank="' . $this->categories[0]['rank'] . '"><span class="sign" x-on:click="openList">+</span><span class="content">' . $this->categories[0]['name'] . '</span></li>';
}
public function render()
{
return view('livewire.product.shopify-new-category')->extends('layouts.app-livewire')->section('content');
}
}
view:
#section('header')
<div id="innerheader" style="display: flex;flex-direction: row;">
<div style="flex:auto">
<h1>Création nouvelle catégorie</h1>
</div>
</div>
#endsection
{{-- section content est mis dans le controller sinon form ne fonctionne pas correctement https://laracasts.com/discuss/channels/livewire/laravel-livewire-submitprevent-not-working-refreshing-page --}}
<form wire:submit.prevent="newCategory">
#csrf
<div class="form-group">
<label for="name">Nom de la catégorie</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Nom de la catégorie"
wire:model="name">
#error('name')
<span class="text-danger">{{ $message }}</span>
#enderror
</div>
<div class="form-group">
<label for="parent" id="parent">Catégorie parent: <b></b></label>
<div x-data="categories" id="parent" class="border rounded bg-white overflow-auto" style="height:40vh;">
<ul style="padding-left:2%">
{!! $html !!}
</ul>
</div>
#error('parent')
<span class="text-danger">{{ $message }}</span>
#enderror
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-success mr-1" wire:click="updateValue('save')">Enregistrer</button>
<button type="submit" class="btn btn-primary" wire:click="updateValue('saveRecreate')">Enregistrer et
créer un autre</button>
</div>
</form>
#push('styles')
<style>
.content ul {
list-style: none;
}
span.sign {
margin-right: 6px;
}
.content li {
cursor: pointer;
}
.content li:hover {
background-color: #39F856;
}
</style>
#endpush
<script>
categories = () => {
return {
selected: '',
labelNoticeSelected: $('label#parent b'),
openList: (e) => {
if (e.target.innerText === '+') {
e.target.innerText = '-';
#this.addChildren(e.target.parentNode.getAttribute('data-rank'));
} else if (e.taget.innerText === '-') {
e.target.innerText = '+';
e.target.parentNode.parentNode.querySelector(
`li[data-rank='${e.target.parentNode.getAttribute('data-rank')}']+ul`).style
.display = 'none';
}
}
}
}
</script>
Here is all the code, I am also using alpinejs, when I click on the "+" I want to request db for children of the category I click on (that is ok) then I want it to transform "+" to "-" (that is not ok) so when I click on "-" it hides the children.
thanks for reading all of this and thanks to everyone trying to help.
Either use a shared state between Livewire and Alpine (see docs) or wrap your button in a wire:ignore. (Potentially a wire:ignore.self if the DOM inside of the ignored div does require Livewire updates)

How to pass a value from foreach loop in the view to the controller in ASP.NET Core MVC?

I have a table in my view that its rows are filled by a foreach loop. A part of this table is as follows:
#foreach (var item in Model.PmModel)
{
<td>#Html.DisplayName(item.pmNumber.ToString())</td>
<td>
<button type="button" class="btn btn-info btn-table btn-modal">Upload</button>
</td>
}
I have a button in each rows and by pressing each of them, a modal form is appeared to upload a file. I use the following code to upload the file and fill database columns based on the file information. But I need to take pmId from view to the following action:
public async Task<IActionResult> UploadFile(IFormFile file)
{
if (file != null)
{
if (file.Length > 0)
{
var fileName = Path.GetFileName(file.FileName);
var fileExtension = Path.GetExtension(fileName);
var newFileName = string.Concat(Convert.ToString(Guid.NewGuid()), fileExtension);
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/PmFiles/UploadedByUsers", newFileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var fileElements = new Models.FileRepository()
{
fileId = 0,
fileName = newFileName,
isDownloaded = false,
pm = _pmRepository.GetPmById(int Id), //I need to get Id from view
uploadDate = DateTime.Now,
};
_fileRepository.InsertFile(fileElements);
_fileRepository.SaveChanges();
}
}
return RedirectToAction("PmPage");
}
I use Bootstrap modal:
#section Modal{
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"
dir="ltr">
<div class="modal-dialog">
<form method="post" enctype="multipart/form-data" asp-controller="Page" asp-action="UploadFile">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">File Upload</h5>
<button type="button" class="btn-close" data-mdb-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row mt-2" dir="rtl">
<label class="form-label" for="customFile">Select your file:</label>
<input type="file" name="file" class="form-control" id="customFile" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-mdb-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger">Upload</button>
</div>
</div>
</form>
</div>
</div>
}
In view, I can find pmId using item.pmNumber but I don't know how I can take its value to my controller. Please help me.
Update: This script triggers the modal by pressing the button.
<script type="text/javascript">
$(document).ready(function () {
$('.btn-modal').click(function () {
$('#exampleModal').modal('show');
});
});
</script>
You can add a hidden input in your modal and put the modal body in the foreach section to pass the item.pmNumber to hidden input.
Here is a working demo you could follow:
Model:
public class FileModel
{
public List<PmModel> PmModel { get; set; }
}
public class PmModel
{
public int pmNumber { get; set; }
}
View:
#model FileModel
#{
int i = 0; //add this....
}
#foreach (var item in Model.PmModel)
{
<td>#Html.DisplayName(item.pmNumber.ToString())</td>
<td> //change here....
<button type="button" data-toggle="modal" data-target="#exampleModal_#i" class="btn btn-info btn-table btn-modal">Upload</button>
</td> //change here.....
<div class="modal fade" id="exampleModal_#i" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"
dir="ltr">
<div class="modal-dialog">
<form method="post" enctype="multipart/form-data" asp-controller="Page" asp-action="UploadFile">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">File Upload</h5>
<button type="button" class="btn-close" data-mdb-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row mt-2" dir="rtl">
<!--add this-->
<input hidden name="id" value="#item.pmNumber" />
</div>
<div class="row mt-2" dir="rtl">
<label class="form-label" for="customFile">Select your file:</label>
<input type="file" name="file" class="form-control" id="customFile" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-mdb-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger">Upload</button>
</div>
</div>
</form>
</div>
</div>
i++; //add here.........
}
#section Scripts {
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Google Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap">
<!-- Bootstrap core CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/css/mdb.min.css" rel="stylesheet">
<!-- JQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Bootstrap tooltips -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/umd/popper.min.js"></script>
<!-- Bootstrap core JavaScript -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"></script>
<!-- MDB core JavaScript -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/js/mdb.min.js"></script>
}
Controller:
public class PageController : Controller
{
public async Task<IActionResult> UploadFile(IFormFile file,int id)
{
//do your stuff...
return View();
}
}
Besides, you can also create a partial view for modal(This partial view still needs a hidden input) to avoid looping modal body code. Refer to this answer

Description not saving when using summernote

I'm trying to create a page that when you click on the create product button
a modal pops up and then you enter whatever you like.
I'm using summernote as my WYSIWYG editor and I'm also using vue as my frontend.
The problem I'm having is that my description isn't being saved.
In my layouts.app I have summernote's cdn.
Here is my code
My Create.vue
<template>
<transition name="modal-fade">
<div>
<div class="modal-backdrop show"></div>
<div class="modal" style="display: inline;">
<div class="modal-dialog modal-dialog-scrollable" role="document" style="width: 680px; max-width: 680px;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Create Product</h5>
<button type="button" class="close" #click="close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div>
<label>Name</label>
<input type="text" class="form-control" v-model="name">
</div>
<div class="mt-2">
<label>Description</label>
<textarea id="summernote" v-model="description"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" #click="close">Close</button>
<button type="button" class="btn btn-success" #click="save">Save</button>
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
props: [],
data() {
return {
name: null,
description: null,
}
},
methods: {
close() {
this.$emit('close');
},
save() {
var description = document.getElementById("summernote").value;
axios.post('/admin/products', {
name: this.name,
description: description,
}).then((response) => {
});
}
},
mounted(){
$('#summernote').summernote();
}
}
</script>
<style>
.modal-fade-enter,
.modal-fade-leave-active {
opacity: 0;
}
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity .25s ease

Updating vue file on changes - Laravel Echo Pusher Notifications

So for the past few days i have tried to make this template auto reload when something new has happened. That is when "Notifications" has been modified, either by new entry has ben added or that a notification has been marked as read.
I use a dropdown to show the results, and right now i have to reload the whole page when something happens. Which isn't very nice for a modern application.
PS. I'm completely new to Vue, since this integration with laravel notifications.
This is my .vue file (and you can see i have tried a few things myself without success)
<template>
<li class="dropdown">
<a href="#" class="dropdown-toggle icons" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false">
<span class="badge badge-dark badge-corner fs-11">{{ notifications.length }}</span>
<i class="fas fa-bell fs-15" style="color: #444;"></i>
</a>
<ul
class="dropdown-menu dropdown-menu-right notify-drop">
<li>
<div class="notify-drop-title">
<div class="row">
<div class="col-10">Notifikationer (<b>{{ notifications.length }}</b>)</div>
<div class="col-2 text-right">
<button class="rIcon allRead"
data-tooltip="tooltip"
data-placement="bottom"
title="Markera alla som lästa"><i
class="fa fa-bullseye fs-12"></i>
</button>
</div>
</div>
</div>
<!-- end notify title -->
<!-- notify content -->
<div class="drop-content">
<div class="thisItem" v-for="notification in notifications" :key="notification.id">
<div class="row pl-10">
<div class="col-1">
<div
v-if="notification.data.type === 'friend' || notification.data.type === 'friendAccept'">
<i class="fas fa-heart fs-25 primary mt-5"></i>
</div>
<div v-if="notification.data.type === 'friendDeny'">
<i class="fas fa-heart-broken fs-25 primary mt-5"></i>
</div>
</div>
<div class="col-10 ml-5">
<button class="float-right rIcon mr-1" data-toggle="tooltip"
data-placement="top" title="Markera som läst"
v-on:click="MarkAsRead(notification)">
<i class="fa fa-bullseye fs-12"></i>
</button>
<a class="fs-14 m-0" style="text-transform: none;" :href="'/profile/' + notification.data.accessurl">{{
notification.data.fromuser }}</a>
<span class="fs-12 m-0 text-muted">{{ notification.data.message }}</span>
<div v-if="notification.data.type === 'friend'">
<button type="button" class="btn btn-primary btn-sm"
v-on:click="AcceptFriend(notification)">Acceptera
</button>
<button type="button" class="btn btn-primary btn-sm"
v-on:click="DenyFriend(notification)">Neka
</button>
</div>
</div>
</div>
</div>
</div>
<div class="notify-drop-footer text-center">
<i class="fa fa-eye"></i> Visa Alla
</div>
</li>
</ul>
</li>
</template>
<script>
export default {
props: ['notifications'],
methods: {
MarkAsRead: function (notification) {
const data = {
id: notification.id
};
const self = notification;
axios.post('/notification/read', data).then(response => {
//self.id = '';
//self.$forceUpdate();
//self.notification += 1;
//self.setState({notification: response.data});
//self.data.fromuser = '';
//self.data.message = response.data;
//this.notifications.splice(notification,1);
console.log(response.data);
});
},
AcceptFriend: function (notification) {
const data = {
id: notification.id,
friendid: notification.data.itemid,
fromuserid: notification.data.fromuserid
};
axios.post('/notification/acceptFriend', data).then(response => {
console.log(response.data);
});
axios.post('/notification/read', data).then(response => {
console.log(response.data);
});
},
DenyFriend: function (notification) {
const data = {
id: notification.id,
friendid: notification.data.itemid,
fromuserid: notification.data.fromuserid
};
axios.post('/notification/denyFriend', data).then(response => {
console.log(response.data);
});
axios.post('/notification/read', data).then(response => {
console.log(response.data);
});
}
}
}
</script>
My app.js
Vue.component('notification', require('./components/Notification.vue'));
const app = new Vue({
el: '#app',
data: {
notifications: ''
},
created() {
axios.post('/notification/get').then(response => {
this.notifications = response.data;
});
var userId = $('meta[name="userId"]').attr('content');
Echo.private('App.User.' + userId).notification((notification) => {
this.notifications.push(notification);
});
},
computed: {
notifications: function () {
return this
}
}
});
Thank you in advance for anyone who can help me solve this!
As I understand it, do you want to render multiple notifications each time you receive new notifications data?
In such a case, you can use props.
if you inject props to notification component, the notification component will be re-rendered whenever the props changes
example
<notification :notifications='notifications'><notification>
https://v2.vuejs.org/v2/guide/components-props.html

Bootstrap 3 - How to load content in modal body via AJAX?

As you can see here, I have a button that launches a modal. Setting an href url for the button this url is automatically loaded into modal by Bootstrap 3.
The fact is this page is loaded into modal root (as said in the bootstrap 3 documentation for modals usage). I want to load it into the modal-body instead.
Is there a way to do it via attributes (not javascript)? Or what is the most automatic way to do it?
P.S. I remember in Bootstrap 2 the content was loaded in the body, not the root.
This is actually super simple with just a little bit of added javascript. The link's href is used as the ajax content source. Note that for Bootstrap 3.* we set data-remote="false" to disable the deprecated Bootstrap load function.
JavaScript:
// Fill modal with content from link href
$("#myModal").on("show.bs.modal", function(e) {
var link = $(e.relatedTarget);
$(this).find(".modal-body").load(link.attr("href"));
});
Html (based on the official example):
<!-- Link trigger modal -->
<a href="remoteContent.html" data-remote="false" data-toggle="modal" data-target="#myModal" class="btn btn-default">
Launch Modal
</a>
<!-- Default bootstrap modal example -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<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" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
...
</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>
Try it yourself: https://jsfiddle.net/ednon5d1/
Check this SO answer out.
It looks like the only way is to provide the whole modal structure with your ajax response.
As you can check from the bootstrap source code, the load function is binded to the root element.
In case you can't modify the ajax response, a simple workaround could be an explicit call of the $(..).modal(..) plugin on your body element, even though it will probably break the show/hide functions of the root element.
I guess you're searching for this custom function. It takes a data-toggle attribute and creates dynamically the necessary div to place the remote content. Just place the data-toggle="ajaxModal" on any link you want to load via AJAX.
The JS part:
$('[data-toggle="ajaxModal"]').on('click',
function(e) {
$('#ajaxModal').remove();
e.preventDefault();
var $this = $(this)
, $remote = $this.data('remote') || $this.attr('href')
, $modal = $('<div class="modal" id="ajaxModal"><div class="modal-body"></div></div>');
$('body').append($modal);
$modal.modal({backdrop: 'static', keyboard: false});
$modal.load($remote);
}
);
Finally, in the remote content, you need to put the entire structure to work.
<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"></h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
Close
Button
Another button...
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
In the case where you need to update the same modal with content from different Ajax / API calls here's a working solution.
$('.btn-action').click(function(){
var url = $(this).data("url");
$.ajax({
url: url,
dataType: 'json',
success: function(res) {
// get the ajax response data
var data = res.body;
// update modal content here
// you may want to format data or
// update other modal elements here too
$('.modal-body').text(data);
// show modal
$('#myModal').modal('show');
},
error:function(request, status, error) {
console.log("ajax call went wrong:" + request.responseText);
}
});
});
Bootstrap 3 Demo
Bootstrap 4 Demo
A simple way to use modals is with eModal!
Ex from github:
Link to eModal.js <script src="//rawgit.com/saribe/eModal/master/dist/eModal.min.js"></script>
use eModal to display a modal for alert, ajax, prompt or confirm
// Display an alert modal with default title (Attention)
eModal.ajax('your/url.html');
$(document).ready(function () {/* activate scroll spy menu */
var iconPrefix = '.glyphicon-';
$(iconPrefix + 'cloud').click(ajaxDemo);
$(iconPrefix + 'comment').click(alertDemo);
$(iconPrefix + 'ok').click(confirmDemo);
$(iconPrefix + 'pencil').click(promptDemo);
$(iconPrefix + 'screenshot').click(iframeDemo);
///////////////////* Implementation *///////////////////
// Demos
function ajaxDemo() {
var title = 'Ajax modal';
var params = {
buttons: [
{ text: 'Close', close: true, style: 'danger' },
{ text: 'New content', close: false, style: 'success', click: ajaxDemo }
],
size: eModal.size.lg,
title: title,
url: 'http://maispc.com/app/proxy.php?url=http://loripsum.net/api/' + Math.floor((Math.random() * 7) + 1) + '/short/ul/bq/prude/code/decorete'
};
return eModal
.ajax(params)
.then(function () { alert('Ajax Request complete!!!!', title) });
}
function alertDemo() {
var title = 'Alert modal';
return eModal
.alert('You welcome! Want clean code ?', title)
.then(function () { alert('Alert modal is visible.', title); });
}
function confirmDemo() {
var title = 'Confirm modal callback feedback';
return eModal
.confirm('It is simple enough?', 'Confirm modal')
.then(function (/* DOM */) { alert('Thank you for your OK pressed!', title); })
.fail(function (/*null*/) { alert('Thank you for your Cancel pressed!', title) });
}
function iframeDemo() {
var title = 'Insiders';
return eModal
.iframe('https://www.youtube.com/embed/VTkvN51OPfI', title)
.then(function () { alert('iFrame loaded!!!!', title) });
}
function promptDemo() {
var title = 'Prompt modal callback feedback';
return eModal
.prompt({ size: eModal.size.sm, message: 'What\'s your name?', title: title })
.then(function (input) { alert({ message: 'Hi ' + input + '!', title: title, imgURI: 'https://avatars0.githubusercontent.com/u/4276775?v=3&s=89' }) })
.fail(function (/**/) { alert('Why don\'t you tell me your name?', title); });
}
//#endregion
});
.fa{
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://rawgit.com/saribe/eModal/master/dist/eModal.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/united/bootstrap.min.css" rel="stylesheet" >
<link href="http//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<div class="row" itemprop="about">
<div class="col-sm-1 text-center"></div>
<div class="col-sm-2 text-center">
<div class="row">
<div class="col-sm-10 text-center">
<h3>Ajax</h3>
<p>You must get the message from a remote server? No problem!</p>
<i class="glyphicon glyphicon-cloud fa-5x pointer" title="Try me!"></i>
</div>
</div>
</div>
<div class="col-sm-2 text-center">
<div class="row">
<div class="col-sm-10 text-center">
<h3>Alert</h3>
<p>Traditional alert box. Using only text or a lot of magic!?</p>
<i class="glyphicon glyphicon-comment fa-5x pointer" title="Try me!"></i>
</div>
</div>
</div>
<div class="col-sm-2 text-center">
<div class="row">
<div class="col-sm-10 text-center">
<h3>Confirm</h3>
<p>Get an okay from user, has never been so simple and clean!</p>
<i class="glyphicon glyphicon-ok fa-5x pointer" title="Try me!"></i>
</div>
</div>
</div>
<div class="col-sm-2 text-center">
<div class="row">
<div class="col-sm-10 text-center">
<h3>Prompt</h3>
<p>Do you have a question for the user? We take care of it...</p>
<i class="glyphicon glyphicon-pencil fa-5x pointer" title="Try me!"></i>
</div>
</div>
</div>
<div class="col-sm-2 text-center">
<div class="row">
<div class="col-sm-10 text-center">
<h3>iFrame</h3>
<p>IFrames are hard to deal with it? We don't think so!</p>
<i class="glyphicon glyphicon-screenshot fa-5x pointer" title="Try me!"></i>
</div>
</div>
</div>
<div class="col-sm-1 text-center"></div>
</div>
create an empty modal box on the current page and below is the ajax call you can see how to fetch the content in result from another html page.
$.ajax({url: "registration.html", success: function(result){
//alert("success"+result);
$("#contentBody").html(result);
$("#myModal").modal('show');
}});
once the call is done you will get the content of the page by the result to then you can insert the code in you modal's content id using.
You can call controller and get the page content and you can show that in your modal.
below is the example of Bootstrap 3 modal in that we are loading content from registration.html page...
index.html
------------------------------------------------
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
function loadme(){
//alert("loadig");
$.ajax({url: "registration.html", success: function(result){
//alert("success"+result);
$("#contentBody").html(result);
$("#myModal").modal('show');
}});
}
</script>
</head>
<body>
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" onclick="loadme()">Load me</button>
<!-- Modal -->
<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" id="contentBody">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</body>
</html>
registration.html
--------------------
<!DOCTYPE html>
<html>
<style>
body {font-family: Arial, Helvetica, sans-serif;}
form {
border: 3px solid #f1f1f1;
font-family: Arial;
}
.container {
padding: 20px;
background-color: #f1f1f1;
width: 560px;
}
input[type=text], input[type=submit] {
width: 100%;
padding: 12px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
input[type=checkbox] {
margin-top: 16px;
}
input[type=submit] {
background-color: #4CAF50;
color: white;
border: none;
}
input[type=submit]:hover {
opacity: 0.8;
}
</style>
<body>
<h2>CSS Newsletter</h2>
<form action="/action_page.php">
<div class="container">
<h2>Subscribe to our Newsletter</h2>
<p>Lorem ipsum text about why you should subscribe to our newsletter blabla. Lorem ipsum text about why you should subscribe to our newsletter blabla.</p>
</div>
<div class="container" style="background-color:white">
<input type="text" placeholder="Name" name="name" required>
<input type="text" placeholder="Email address" name="mail" required>
<label>
<input type="checkbox" checked="checked" name="subscribe"> Daily Newsletter
</label>
</div>
<div class="container">
<input type="submit" value="Subscribe">
</div>
</form>
</body>
</html>

Resources