I'm using ASP.net MVC5 with Bootstrap 3
I have the following View
#model WilhanWebsite.Models.PhotoViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Gallery</h2>
<p>
#Html.ActionLink("Upload Photo", "Create")
<br/>
#for (var i = 0; i < Model.DownloadedImages.Count; i++)
{
<a data-toggle="modal" data-target="#img-thumbnail#i" class="img_modal" href="data:image/jpg;base64,#(Convert.ToBase64String(Model.DownloadedImages[i].ImageData))">
<img id="img-thumbnail#i" class="img-thumbnail" src="data:image/jpg;base64,#(Convert.ToBase64String(Model.DownloadedImages[i].ImageData))" alt="#Model.DownloadedImages[i].Description" />
</a>
}
<div id="modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Title to go here</h3>
</div>
<div class="modal-body">
<img id="modal_img_target">
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
</p>
When I click an image from the gallery I would like it to display in a modal window.
My problem is, when I click the link, the modal window displays without the image. All the examples I've seen use images from the file system whereas my site uses images from a db via a byte array. I guess the fix may be to change the line of javascript that is assigning the source attribute on the modal image but I've tried various things here without a result. The problem can be seen at the following address: Problem page
** EDIT **
Updated view to use for loop to identify images as suggested. Problem changed, now rather than displaying a blank modal page, the image is displayed on a blank page.
** EDIT Working View **
#model WilhanWebsite.Models.PhotoViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Gallery</h2>
<p>
#Html.ActionLink("Upload Photo", "Create")
<br/>
#for (var i = 0; i < Model.DownloadedImages.Count; i++)
{
<a data-toggle="modal" data-target="#img-thumbnail#i" class="img_modal" href="data:image/jpg;base64,#(Convert.ToBase64String(Model.DownloadedImages[i].ImageData))">
<img id="img-thumbnail#i" class="img-thumbnail" src="data:image/jpg;base64,#(Convert.ToBase64String(Model.DownloadedImages[i].ImageData))" alt="#Model.DownloadedImages[i].Description" />
</a>
}
<div id="modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Title to go here</h3>
</div>
<div class="modal-body">
<img id="modal_img_target">
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
</p>
<script type="text/javascript">
$('.img_modal').on('click', function (e) {
e.preventDefault();
$("#modal_img_target").attr("src", this);
$("#modal").removeClass("hide");
$('#modal').modal('show');
});
</script>
You need to add the toggle and target to the link:
<a ... data-toggle="modal" data-target="#img-thumbnail1"
Then add the target id to the image:
<img id="img-thumbnail1" class="img-thumbnail"
This means that you will have to add an incrementing number to the loop so that id's are unique.
You can do this like this:
#for (var i = 0; i < Model.DownloadedImages.Count; i++)
{
<a data-toggle="modal" data-target="#img-thumbnail#i" class="img_modal" href="data:image/jpg;base64,#(Convert.ToBase64String(photo.ImageData))">
<img id="img-thumbnail#i" class="img-thumbnail" src="data:image/jpg;base64,#(Convert.ToBase64String(photo.ImageData))" alt="#photo.Description" />
</a>
}
The problem is with your jquery, as you are getting the "#modal_img_target" src value correctly. Your onClick event is hiding the image.
Try this :-
<script type="text/javascript">
$('.img_modal').on('click', function (e) {
e.preventDefault();
$("#modal_img_target").attr("src", this);
$("#modal").removeClass("hide");
$('#modal').modal('show');
});
</script>
Related
I need to pass a Model to a partial view. I first pass a value of ID, then I get the Model I need based on that ID.
The scenario: I have a table with a delete button in each row. I need to display a confirmation bootstrap modal that includes a Model.
The problem, it's not working and I don't know if there another way to do that or not
In the section of javascript BPCategoriesId not recognized
Here is my code attempt.
Delete Button
#foreach (var item in Model.BPCategories)
{
...
<button type="button" data-id="#item.Id" class="btn btn-outline-danger w-50" data-bs-toggle="modal" data-bs-target="#exampleModal">
Delete
</button>
...
}
Bootstrap Modal
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Confirm Delete</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="ModelLoad">
<!--here I need to load my partial view with a model using JS-->
</div>
<!--<partial name="Delete" model="#Model.BPCategories.Where(id => id.Id == returnID()).FirstOrDefault()" />-->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form asp-action="Delete">
<input type="hidden" asp-for="Id" />
</form>
</div>
</div>
</div>
</div>
JavaScript
<script>
$(document).ready(function () {
var btns = document.querySelectorAll('[data-id]');
for (let btn of btns) {
btn.addEventListener('click', () => {
let BPCategoriesId = btn.dataset['id'];
var jsonModel = #Html.Raw(Json.Serialize(#Model.BPCategories.Where(id => id.Id == BPCategoriesId).FirstOrDefault()));
$("#ModelLoad").load('#Url.Action("Delete", "BootstrapCategories")', jsonModel);
});
}
});
</script>
#model LoadPartialView.Models.TestViewModel
#foreach (var item in Model.BPCategories)
{
<p>
<button type="button" data-id="#item.Id" class="btn btn-outline-danger w-50" data-toggle="modal" data-target="#exampleModal">
Delete
</button>
</p>
}
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Confirm Delete</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="modelLoad">
<!--here I need to load my partial view with a model using JS-->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<form asp-action="Delete">
<input type="hidden" asp-for="Id" />
</form>
</div>
</div>
</div>
</div>
#section scripts {
<script type="text/javascript">
$(function () {
var btns = document.querySelectorAll('[data-id]');
for (let btn of btns) {
btn.addEventListener('click', () => {
let bpCategoryId = btn.dataset['id'];
$("#modelLoad")
.load('#Url.Action("Delete", "BootstrapCategories")', {
bpCategories: JSON.parse('#Html.Raw(Json.Encode(Model.BPCategories))'),
bpCategoryId: bpCategoryId
});
});
}
});
</script>
}
Demo is pushed to GitHub.
Today I came across with this, I tried doing what was in the project and came across with the OP's problem about the full screen modal. I saw a solution below about about cutting the div and pasting it in an outer div.
I did what was in the solution but what happens is that the full modal div is retained and the normal popup shows.
If I add it to the script, no popup shows but backdrop changes.
How do I solve this? Thanks in advance
UPDATE
PARENT VIEW BUTTON
<button type="button" class="btn btn-success btn-sm modal-link" data-targeturl="#Url.Action("_Popup","Application",new { MotorId = item.motor_id, Serialno = item.serialno, AppNo = item.application_no, Remarks = item.remarks })"> View
</button>
PARENT MODAL
<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
X
<div class="modal-content">
<div class="modal-body"></div>
</div>
</div>
SCRIPT
$(function () {
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$("#modal-container").remove();
$.get($(this).data("targeturl"), function (data) {
$('<div id="modal-container" class="modal fade">' + '<div class="modal-content" id="modalbody" >' + data + '</div></div>').modal();
});
});
});
PARTIAL VIEW
#model iVehicle.ViewModel.FranchiseViewModel
<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">
<p>Some content here</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>
I followed a great little solution over at CodeProject for injecting partial views into bootstrap modals with no explicit ajax calls required...
https://www.codeproject.com/Tips/826002/Bootstrap-Modal-Dialog-Loading-Content-from-MVC-Pa
In a nutshell, the author does this (UPDATE: I have added modal-dialog, which the author doesn't do but is required):
_Layout
<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content"></div>
</div>
</div>
<script>
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
</script>
UPDATE - Here's the _Partial
<div class="modal-header">
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
</div>
... and by doing so makes any link with class="modal-link" inject its result to the modal automatically.
Seems wonderfully simple and elegant, but just one problem: The data-target he specifies is the <div id="modal-container">. Really? Why? The content should be injected into the <div class="modal-content">, shouldn't it? But nearly everyone has no problem, and no one mentions this conundrum. For me, the solution does exactly what he's told it to, it injects into <div id="modal-container">, thereby overwriting <div class="modal-content"> with my modal-body, etc. that are the contents of my partial view, so the display is messed up -- full width of the window and transparent, because it's not going into the modal-content.
Am I missing something here?
UPDATE
One of Stom's answers below is correct (I've marked it). However, as I've shown in updates above, I actually already had the <div class="modal-dialog" role="document"> in the _Layout and <div class="modal-header">, body, and footer in the _Partial. Ultimately, after this issue persisted for days, I woke up today and it just started working with no changes! Seriously? Frustrating. The problem previously was that the data-toggle was causing it to actually inject into the #modal-container, not the .modal-content. But now it started to function as Stom says the documentation says, which is that even though you set the data-toggle as the #modal-container, Bootstrap should inject it into the .modal-content. Why that was not happening before but is now, I haven't the foggiest. I haven't upgraded versions overnight or anything. Ghost problem ---
The content should be injected into the ,
shouldn't it?
Before version 3.1 it should be injected root element of modal i.e your modal-container But on version 3.1 it has changed. And now the bootstrap docs says it will be injected in modal-content.
modal-content with my modal-body, etc. that are the
contents of my partial view, so the display is messed up , Why?
Because your partial view should contain modal-body and not modal-content.
Also Adding modal-dialog inside model root element solves the syling issue.
So below setup should work for you:
Action Methods
public ActionResult Index()
{
return View();
}
public ActionResult GetPartialData()
{
return PartialView("_ExamplePartial");
}
Index View
<!-- Button trigger modal -->
<a data-toggle="modal" href="#Url.Action("GetPartialData","Home")" data-target="#myModal">Click me</a>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
</div>
</div>
</div>
_ExamplePartial View
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<h1>Remote Partial Content</h1>
</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>
Note:
This option is deprecated since v3.3.0 and has been removed in v4.
Reference:
1.
2.
Below Setup should work to inject partial view content into modal body and it doesn't mess up with your default bootstrap modal style.
Action Methods
public ActionResult Index()
{
return View();
}
public PartialViewResult GetSomeData()
{
System.Threading.Thread.Sleep(2000); // Just to show delay to Get data
ViewBag.Message = "Example Data from Server"; //Using ViewBag Just for example, use ViewModel Instead
return PartialView("~/Views/Shared/_ExamplePartial.cshtml");
}
Index View
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" id="btnGetData">
Get Modal With Partial
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="partialViewContent">
</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>
_ExamplePartial View
<h2>Partial View Contents</h2>
<h3>#ViewBag.Message</h3>
<p>Some More Static Content</p>
Script:
<script>
$(document).ready(function () {
$('#btnGetData').click(function () {
var requestUrl = '#Url.Action("GetSomeData", "Home")';
$.get(requestUrl)
.done(function (responsedata) {
console.log("success");
$("#partialViewContent").html(responsedata);
$('#myModal').modal('show')
})
.fail(function () {
alert("error");
})
.always(function () {
console.log("finished");
});
})
});
</script>
I am trying to do this under ASP.NET MVC 5 Visual Studio 2013, with the latest nuget libraries.
AngularJS Core 1.3.8
AngularJS UI Bootstrap 0.12.0
Bootstrap 3.3.1
jQuery 2.1.3
Important files:
App.js
var deviceModule = angular.module("devicesModule", ["ui.bootstrap"]);
var app = angular.module("dxuWebApp", ["devicesModule"]);
DeviceController.js
deviceModule.controller("DevicesController", function ($scope, deviceService, $modal) {
$scope.devices = [];
function init() {
$scope.devices = deviceService.getDevices();
}
init();
$scope.addDevice = function(size) {
var modalInstance = $modal.open({
templateUrl: "newDeviceTemplate.html",
controller: "NewDeviceModelController",
size: size
});
modalInstance.opened.then(function() {
alert('yep');
});
modalInstance.result.then(function (newDevice) {
deviceService.postDevice(newDevice);
}, function () {
});
}
});
deviceModule.controller("NewDeviceModelController", function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close({ name: newDevice.name });
};
$scope.cancel = function () {
$modalInstance.dismiss("cancel");
};
});
newDeviceTemplate.html
<div class="modal-header">
<h2>New Device</h2>
</div>
<div class="modal-body">
<input type="text" data-ng-model="newDevice.name" />
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
Index.cshtml
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div data-ng-app="dxuWebApp" data-ng-controller="DevicesController">
<div class="row">
<div class="col-lg-12">
<h2>Devices <a data-ng-click="addDevice()"><span class="glyphicon glyphicon-plus-sign"></span></a></h2>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<ul class="list-inline">
<li data-ng-repeat="device in devices | orderBy: 'name'">
<a href="#">
<div class="device">
<div class="deviceImage">
#*<img alt="device image"/>*#
<span class="glyphicon glyphicon-phone"></span>
</div>
<div class="deviceName">
{{device.name | uppercase}}
</div>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
#section scripts
{
#Scripts.Render("~/bundles/dxuWebApp")
<script type="text/ng-template" id="newDevice.html">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h2>New Device</h2>
</div>
<div class="modal-body">
<input type="text" data-ng-model="newDevice.name" />
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</div>
</div>
</script>
}
The references to both ui-bootstrap and ui-bootstrap.tpls are in the _layout page.
I was hoping that when I clicked
<a data-ng-click="addDevice()"><span class="glyphicon glyphicon-plus-sign">
AngularJs magic would happen and I would get a modal on the screen, but nothing happens, no errors or anything like that.
I did put a break point on deviceController.addDevice() and it hit that point and goes through, nothing appear on the screen.
So what wrong with my code?
I had the exact same problem.
I am using MVC 5.0 with AngularJS so the reason it wasn't working ( I was getting a 404 not able to find the modal.html.) was I didn't create a route in the controller for the modal.html or map a view to the controller with the same name as the route.
After properly setting up the Controller and the View it worked.
Sorry there is no code for this since it was just a problem following the MVC process.
I have a bootstrap modal dialog that is inside a form. The form is submitted via AJAX. I want the submit button to also dismiss the modal (otherwise i end up with the modal overlay remaining)
Code for the modal is:
#using (Ajax.BeginForm("SaveConfiguredReport", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "report-details", OnBegin="preProcessing" }))
{
<div class="modal fade" id="add-filter-dialog" tabindex="-1" role="dialog" aria-labelledby="add-filter-dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4>Add a Filter</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<p>Adding filters allows you to sort what data will be included in the report. These filters will be default for all ongoing usage of this report.</p>
<div id="field-templates"></div>
<input type="hidden" id="field-template-id" name="FieldTemplateID" />
#Html.DropDownList("OperatorID", Model.Operators.Select(x => new SelectListItem { Text = x.Name, Value = x.OperatorID.ToString() }))
<input type="text" name="FilterValue" class="typeahead" id="filter-value" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-success" data-dismiss="modal" name="Command" value="Add">Add Filter</button>
</div>
</div>
</div>
</div>
}
<!-- other code -->
<script>
function preProcessing() {
$('.modal').each(function (index, element) {
$(element).modal('hide');
});
}
</script>
If i keep the data-dismiss attribute on the submit button, it will dismiss the form but not submit it. If i remove it, the form will be submitted but not dismissed. Anyone had any luck with this?
EDIT
I have added a pre-processor to the AJAX call to hide all forms at the start. Hiding them at the end did not work because the form was replacing the modal but not the overlay. This is a workaround until a proper solution is suggested
What I usually do is close it via Javascript after the form has been validated and AJAX post/get was successful.
$('#add-filter-dialog').modal('hide');
See more options here http://getbootstrap.com/javascript/#modals-usage