I've been trying to work this out for the past few days and I wondered if anyone might be able to get me over the line with it.
The problem I have is that I want to add a new value to the database and then update the partial view without updating the main view which is just a dropdown list and button.
The code I have will currently create the new entry but then it shows the Index/List as its own view, rather than just an updated partial view.
Below is a Main View which a Partial View is rendered to following a button click which renders a partial view based on a dropdown value
@{
ViewData["Title"] = "Manage DropDown Lists";
//Layout = "~/Views/Shared/_Layout.cshtml";
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<h1>Manage Lists</h1>
<p>
Select List:
@Html.DropDownList("ddl", ViewData["selected"] as List<SelectListItem>)
<button id="btn-ddl" data-url='@Url.Action("Index", "param")' >Get List</button>
</p>
<hr />
<br />
<div id="detailsDiv">
</div>
@section Scripts {
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV 4mjoKBsE4x3H BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="~/js/site.js"></script>
}
This is the Jquery for the Button Click (btn-ddl)
//Render PartialView from Button click - input Id from DropDownList - Manage Lists
$(document).ready(function () {
$("body").on("click", '#btn-ddl', function (evt) {
var $detailDiv = $('#detailsDiv'),
url = $(this).data('url');
url = url.replace("param", $("#ddl").val());
$.get(url, function (data) {
$detailDiv.html(data);
});
});
});
This is one of the Partial Views which is rendered. This partialview is an Index of the selected model. It also contains a button to Add a new item to the list, and edit buttons to edit the items in the list.
@model IEnumerable<PoCStaffDatabase.Models.AccessLevel>
<div>
<h1>Access Levels</h1>
<br />
<hr />
</div>
<div id="PlaceHolderHere">
<!-- Modal Popup Placeholder -->
</div>
<button type="button" data-toggle="ajax-modal" data-target="#addAccessLevel" data-url="@Url.Action("Create")" id="showModalPopup">
Create
</button>
<br /><br />
<table >
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.AccessLevelName)
</th>
<th>
@Html.DisplayNameFor(model => model.Live)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.AccessLevelName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Live)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.AccessLevelId">Edit</a>
</td>
</tr>
}
</tbody>
</table>
The 'Create' button (id="showModalPopup") is clicked to create a new item, and this is done via a Partial View (below) which appears as a Modal Popup.
@model PoCStaffDatabase.Models.AccessLevel
<div id="addAccessLevel" tabindex="-1" role="dialog" aria-labelledby="addAccessLevelLabel" aria-hidden="true">
<div role="document">
<div >
<div >
<h5 id="addAccessLevelLabel">Add Access Level</h5>
<button type="button" data-dismiss="modal" id="btnClose" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div >
<form asp-action="Create">
<div >
<label asp-for="AccessLevelName" ></label>
<input asp-for="AccessLevelName" />
<span asp-validation-for="AccessLevelName" ></span>
</div>
<div >
<label >
<input asp-for="Live" /> @Html.DisplayNameFor(model => model.Live)
</label>
</div>
<div >
<button type="button" data-dismiss="modal" id="btnClose" >Cancel</button>
<button type="submit" data-save="modal" data-url='@Url.Action("Index", "AccessLevels")'id="btnSave">Create New</button>
</div>
</form>
</div>
</div>
</div>
</div>
This is the Jquery code which runs from the 'Create New' button (id="btnSave"). I have left in the last thing I tried in order to update the partial view but it's commented out.
Again even with that part in the code the partial view renders as a full view (without formatting as the _Layout view isn't shown either.
$(document).ready(function () {
$('body').on("click", '#showModalPopup', function (event) {
var PlaceHolderElement = $('#PlaceHolderHere'),
url = $(this).data('url');
PlaceHolderElement.empty();
$.get(url, function (data) {
PlaceHolderElement.html(data);
PlaceHolderElement.find('.modal').modal('show');
});
});
PlaceHolderElement.on("click", '#btnSave', function (event) {
form = $(this).parents('.modal').find('form'),
actionUrl = form.attr('action'),
sendData = form.serialize();
$.post(actionUrl, sendData).done(function (data) {
PlaceHolderElement.find('.modal').modal('hide');
});
// var $detailDiv = ('#detailsDiv'),
// url = $(this).data('url');
//
// $.get(url, function (data) {
// $detailDiv.html(data);
// });
});
});
Finally this is the Controller for the Create and Index actions.
namespace PoCStaffDatabase.Controllers
{
public class AccessLevelsController : Controller
{
private readonly AppDbContext _context;
public AccessLevelsController(AppDbContext context)
{
_context = context;
}
// GET: AccessLevels
public async Task<IActionResult> Index()
{
var accesslevel = await _context.AccessLevel.ToListAsync();
return PartialView("_partialIndex", accesslevel);
//return View(await _context.AccessLevel.ToListAsync());
}
// GET: AccessLevels/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var accessLevel = await _context.AccessLevel
.FirstOrDefaultAsync(m => m.AccessLevelId == id);
if (accessLevel == null)
{
return NotFound();
}
return View(accessLevel);
}
// GET: AccessLevels/Create
public IActionResult Create()
{
AccessLevel accesslevel = new AccessLevel();
return PartialView("_partialCreate", accesslevel);
}
// POST: AccessLevels/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("AccessLevelId,AccessLevelName,Live")] AccessLevel accessLevel)
{
if (ModelState.IsValid)
{
_context.Add(accessLevel);
await _context.SaveChangesAsync();
//return NoContent();
return RedirectToAction("Index");
//return PartialView("_partialIndex", await _context.AccessLevel.ToListAsync() );
}
return View(accessLevel);
}
Any help that anyone can give would be greatly appreciated.
Thanks.
CodePudding user response:
You need change the js like below:
$(document).ready(function () {
$('body').on("click", '#showModalPopup', function (event) {
var PlaceHolderElement = $('#PlaceHolderHere'),
url = $(this).data('url');
PlaceHolderElement.empty();
$.get(url, function (data) {
PlaceHolderElement.html(data);
var data = PlaceHolderElement.find('.modal');
//modify here......
$(PlaceHolderElement.find('.modal')).modal('show')
});
//}); remove here
PlaceHolderElement.on("click", '#btnSave', function (event) {
form = $(this).parents('.modal').find('form'),
actionUrl = form.attr('action'),
sendData = form.serialize();
$.post(actionUrl, sendData).done(function (data) {
//modify here......
$(PlaceHolderElement.find('.modal')).modal('hide');
$('#detailsDiv').html(data); //add this...
});
});
});
}) //add this...
Modify your _partialCreate
here:
@model AccessLevel
@*remove fade*@
<div id="addAccessLevel" tabindex="-1" role="dialog" aria-labelledby="addAccessLevelLabel" aria-hidden="true">
<div role="document">
<div >
<div >
<h5 id="addAccessLevelLabel">Add Access Level</h5>
<button type="button" data-dismiss="modal" id="btnClose" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div >
<form asp-action="Create">
<div >
<label asp-for="AccessLevelName" ></label>
<input asp-for="AccessLevelName" />
<span asp-validation-for="AccessLevelName" ></span>
</div>
<div >
<label >
<input asp-for="Live" /> @Html.DisplayNameFor(model => model.Live)
</label>
</div>
<div >
<button type="button" data-dismiss="modal" id="btnClose">Cancel</button>
@*change here.........*@
<button type="button" data-save="modal" data-url='@Url.Action("Index", "AccessLevels")' id="btnSave">Create New</button>
</div>
</form>
</div>
</div>
</div>
</div>
Backend code:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("AccessLevelId,AccessLevelName,Live")] AccessLevel accessLevel)
{
if (ModelState.IsValid)
{
_context.Add(accessLevel);
await _context.SaveChangesAsync();
return PartialView("_partialIndex", await _context.AccessLevel.ToListAsync() );
}
throw new Exception("xxxxx"); //ajax cannot judge the modelstate error
}