问题
I have a view which does a for each loop over a list of database items. I am looking to have a "Details" action for each one which opens a modal passing the id for each item into it and displays the details for that item in a partial view within that modal.
So far I have the following
@foreach (var item in Model)
{
<a href="#detailsModal" role="button" class="btn" data-toggle="modal">Details</a>
}
<div class="modal fade" id="detailsModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
@{Html.RenderAction("_PartialDetails", "ActivityAds", new { @id = "NEED TO PASS ID HERE" });}
</div>
</div>
</div>
</div>
I am trying to avoid putting the modal in the for each loop as I fear that would be very inefficient having to create a modal for every record. I could be calling the partial view in the Modal wrong as well. I am out of practise Im afraid and I am sure there is a way to do this
Thank you
回答1:
One way would be to use ajax to fill in the container dynamically.
here is an example from an app i have - note that some of the javascript is in an external js file so can't directly use model; model values are stored in hidden fields and/or data-id, data-value attributes for this purpose
@foreach (var assignment in Model.Assignments)
{
<li role="presentation" id="assignmentsDetails_@assignment.AssignmentView.AssignmentViewId" data-id="@assignment.AssignmentView.AssignmentViewId">
<a role="menuitem" onclick="selectCriteria(this);" title="@assignment.AssignmentView.AssignmentViewDescription">Criteria @criteriaNumber</a>
</li>
criteriaNumber++;
}
javascript
function selectCriteria(clickedElement) {
var dataid = $(clickedElement).parent().attr("data-id");
loadAssignmentDetails(dataid);
}
function loadAssignmentDetails(assignmentViewId) {
$.ajax({
type: "GET",
url: Config.RootUrl + "Assignments/Detail/" + assignmentViewId + "/" + $("#AssignmentTypeValueId").val(),
success: function (data) {
$("#assignmentViewDetailsContainer").html(data);
}
});
}
回答2:
Here is my solution based "Nikki9696" answer :) It works perfectly. Thank you very much! Nikki9696
function showDetails(clickedElement) {
var dataid = $(clickedElement).attr("data-id");
showDetailsAjax(dataid);
}
function showDetailsAjax(activityAdID) {
var link = '@Url.Action("_PartialDetails", "ActivityAds", new { id = "-1"})'
link = link.replace("-1", activityAdID);
$.ajax({
type: "GET",
url: link,
error: function(data)
{},
success: function (data) {
$("#detailsModal .modal-body").html(data);
$('#detailsModal').modal('show');
},
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div class="modal fade" id="detailsModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body"></div>
</div>
</div>
</div>
@foreach (var item in Model)
{
<a onclick="showDetails(this);" id="activityAdDetails_@item.ad_id" data-id="@item.ad_id">Details</a>
}
回答3:
I have an alternative, similar but different enough that I thought it worth sharing - I wanted to use unobtrusive jquery to achieve the same thing through attribute mark up only, so I define a separate partial view for the modal and it's script, and include it in my layout page, so that in each other view all I need to do is add markup to use the modal and functionality I built into that partial script. I've added functionality to the modal to allow me to specify a script to call when the modals submit is successful, etc. The dialog content is retrieved from the server (by calling a controller method that returns a partial view - hence the need to disable ajax cache). Heres an example outside of a list which calls the javascript RefreshAll when done:
<button class="btn btn-sm btn-success completeFixtureButton"
data-submittext="Update"
data-modalsubmit="CompleteFixtureForm"
data-modaltitle="Fixture Completed"
data-modalsuccess="RefreshAll();"
data-modalload="@Url.Action("FixtureCompleted", new { fixtureId = fix.Id })">
and here's a similar example but from a link styled as a button instead of a button:
<a class="btn btn-default" href="#"
data-modalsubmit="editLeagueForm"
data-modaltitle="Edit Season"
data-modalsize="lg"
data-modalload="@Url.Action("EditLeaguePartial", "League", new { leagueId = Model.Season.League.Id, seasonId = Model.Season.Id })"><span class="glyphicon glyphicon-white glyphicon-cog"></span>Season Settings</a>
Heres one within a list/table:
<tbody id="clubList">
@foreach (Player p in Model.Club.Players.OrderBy(p => p.LastName))
{
bool playerManager = Model.Club.Managers.Any(m => m.Id == p.Id);
<tr>
<td>
<a href='#' data-modaltitle="@p.FullName" data-modalload="@Url.Action("ContactPlayerPartial", "Player", new { playerId = p.Id })">
<img src="@Url.Action("ProfilePictureById", "Player", new { playerId = p.Id })" style="max-width:3em; margin-right:10px;" class="pull-left" /> @p.FullName
</a>
</td>
</tr>
...
}
and here's the modal partial (_ModalDialogPartial.cshtml) in the Shared Views folder:
<div id="details" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h2 id="detailsHeader"></h2>
</div>
<div class="modal-body">
<div id="detailsBody" ></div>
</div>
<div class="modal-footer">
<a href="#" id="btnModalCancel" class="btn" data-dismiss="modal">Close</a>
<input type="submit" id="btnModalSave" class="btn btn-primary" value="Save"/>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$.ajaxSetup({ cache: false });
initialiseModals();
});
function initialiseModals() {
$('#details').on('shown.bs.modal', function () {
$.validator.unobtrusive.parse($('#details'));
});
$(document).on('click', '*[data-modalload]', function () {
var e = $(this);
if (e.data('submittext') != undefined) {
$('#btnModalSave').html(e.data('submittext'));
} else $('#btnModalSave').html('Save');
if (e.data('class') != undefined) {
var cls = e.data('class');
$('#details').removeClass(cls).addClass(cls);
}
if(e.data('modalsize') != undefined) {
var size = e.data('modalsize');
$('.modal-dialog').addClass('modal-' + size);
}
if (e.data('modalsubmit') == undefined) {
$('#btnModalSave').hide();
$('#btnModalCancel').addClass("btn-primary");
}
else {
$('#btnModalSave').show();
$('#btnModalCancel').removeClass("btn-primary");
$('#btnModalSave').unbind('click').click(function (ctrl) {
$('#btnModalSave').attr('disabled', 'disabled');
ctrl.preventDefault();
var submitUrl = $('#' + e.data('modalsubmit')).attr("action");
var formData = $('#' + e.data('modalsubmit')).serialize();
$.post(submitUrl,
formData,
function (data, status, xhr) {
$('#btnModalSave').removeAttr('disabled');
$('#details').modal('hide');
if (e.data('modalsuccess') != undefined) {
eval(e.data('modalsuccess'));
}
}).error(function () {
$('#btnModalSave').prop('disabled', false);
});
});
}
$('#detailsBody').load(e.data('modalload'), function () {
$('#detailsHeader').html(e.data('modaltitle'));
$('#details').modal('show');
$.validator.unobtrusive.parse($('#detailsBody'));
});
});
}
</script>
来源:https://stackoverflow.com/questions/37844621/open-bootstrap-modal-from-link-for-each-item-in-a-list-in-view-mvc