I'm trying to refresh my Partial View after submitting a form which will be processed in my controller. The problem is that whenever I try to refresh it form my controller, I get redirected to a blank page with content from the Partial View.
Partial View
#model Smarty.Viewmodels.BugViewModel
<div class="modal fade" id="bugModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Bug Reporting Tool</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<form asp-controller="Smarty" asp-action="SendBugReport" enctype="multipart/form-data">
#if (!string.IsNullOrWhiteSpace(ViewBag.message))
{
if (!ViewBag.IsError)
{
<span class="border border-success text-success">#ViewBag.message</span>
}
else
{
<span class="border border-danger text-danger">#ViewBag.message</span>
}
}
<div class="modal-body">
<label asp-for="Description" class="control-label"></label>
<textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
<label asp-for="FormFile" class="control-label"></label><br />
<input asp-for="FormFile" type="file" />
<span asp-validation-for="FormFile" class="text-danger"></span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schliessen</button>
<button type="submit" id="BugReportBtn" class="btn btn-success">Bug Report senden</button>
</div>
</form>
</div>
</div>
</div>
Controller
public async Task<IActionResult> SendBugReport(BugViewModel viewModel)
{
//Process Form
return PartialView("BugModal", viewModel);
}
Thanks in advance!
I get redirected to a blank page with content from the Partial View.
That is expected because you use return PartialView() which will return the simple partial html to render it into the view.
I want to refresh the Partial View with content like Error Messages, Success messages etc
You could not get #ViewBag.message from the SendBugReport action, it is passed from the action of main page.
As the comment has said that, first of all, you could use ajax to submit the form to SendBugReport action.Then the action return message and isError json data to ajax success function. Finally, you render message on the view based on the value of isError:
1.Partial View (Views/Shared/BugModal.cshtml)
#model BugViewModel
<div class="modal fade" id="bugModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Bug Reporting Tool</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<form id="myForm" asp-controller="Smarty" asp-action="SendBugReport" enctype="multipart/form-data">
<div id="result"></div>
<div class="modal-body">
<label asp-for="Description" class="control-label"></label>
<textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
<label asp-for="FormFile" class="control-label"></label><br />
<input asp-for="FormFile" id="FormFile" name="FormFile" type="file" />
<span asp-validation-for="FormFile" class="text-danger"></span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schliessen</button>
<button type="button" id="BugReportBtn" class="btn btn-success">Bug Report senden</button>
</div>
</form>
</div>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script>
$('#BugReportBtn').on('click', function (event) {
var url = "/Smarty/SendBugReport";
var description = document.getElementById("Description").value;
var fileInput = $('#FormFile')[0];
var formFile = fileInput.files[0];
var formData = new FormData();
formData.append("Description", description);
formData.append("FormFile", formFile);
$.ajax({
type: "POST",
url: url,
data: formData,
dataType: "json",
processData:false,
contentType: false,
success: function (data) {
if (!data.isError) {
$("#result").html("<span class='border border-success text-success'>" + data.message + "</span>");
} else {
$("#result").html("<span class='border border-danger text-danger'>" + data.message + "</span>");
}
$('#bugModal').modal('show');
}
});
});
</script>
2.Action
[HttpPost]
public async Task<JsonResult> SendBugReport(BugViewModel viewModel)
{
//Process Form
string message;
bool isError;
//set data to message and isError
return Json(new { message, isError });
}
Related
Maybe I'm looking at this the wrong way, maybe the fact that the browser is showing the view as a pop up doesn't change the fact that for MVC this is just a different View with it's own ViewModel. Since this is a form inside a form in a way, maybe there are better ways to do the following;
The initial view (CreateTimeslot.cshtml) is a form with properties of a workshop to be scheduled. name, description,.., And a speaker multiselect list:
#model MDFrontend.Models.Timeslots.TimeslotManagementViewModel
<div class="form-group">
<label asp-for="StartTime" class="control-label"></label>
<input asp-for="StartTime" type="datetime" class="form-control" value="#startTime" />
<span asp-validation-for="StartTime" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EndTime" class="control-label"></label>
<input asp-for="EndTime" type="datetime" class="form-control" value="#startTime.Add(Model.WorkshopDuration)" readonly />
<span asp-validation-for="EndTime" class="text-danger"></span>
</div>
<!--------------------------------------------------------------SpeakerBox---------------------------------------------------------------------->
<div class="form-group">
<label asp-for="Speakers" class="control-label"></label>
<select asp-for="SpeakerIDs" id="speakerBox" name="SpeakerIDs[]" asp-items="#Model.Speakers" multiple="multiple">
</select>
<span asp-validation-for="SpeakerIDs" class="text-danger"></span> <!--This is not showing, asp-validation-summary does-->
</div>
<button onclick="showFormInPopup('#Url.Action("CreateSpeaker","SpeakerAdmin",Model,Context.Request.Scheme)',
'New Speaker')" type="button" id="btnAddSpeaker" class="btn btn-primary"> #Localizer["Add_Speaker"]
</button>
I'm passing the TimeslotManagementViewModel in the Url.Action method, which I'm mapping to the CreateSpeakerViewModel
public class CreateSpeakerViewModel
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public TimeslotManagementViewModel oldModel { get; set; }
}
This view is shown as a popup:
<!-------------------------------------------Hidden Add Speaker Popup--------------------------------------------------->
<div class="modal" tabindex="-1" role="dialog" id="form-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="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>
</div>
</div>
</div>
<!-------------------------------------------Hidden Add Speaker Popup--------------------------------------------------->
The body of this CreateSpeaker View:
#model MDFrontend.Models.Speakers.CreateSpeakerViewModel
<form asp-action="CreateSpeaker" asp-controller="SpeakerAdmin">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Firstname" class="control-label"></label>
<input asp-for="Firstname" class="form-control" />
<span asp-validation-for="Firstname" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Lastname" class="control-label"></label>
<input asp-for="Lastname" class="form-control" />
<span asp-validation-for="Lastname" class="text-danger"></span>
</div>
<div class="form-group" >
<input type="submit" value="Save" asp-action="CreateSpeaker" asp-controller="SpeakerAdmin"
formmethod="post" class="btn btn-primary" />
</div>
</form>
The CreateSpeaker Post method is receiving this simple form, adding them to the db, redirecting to the initial CreateTimeslot view with an updated multiselect.
[HttpPost]
[Authorize(Roles = RoleConstant.Admin)]
public async Task<IActionResult> CreateSpeaker(CreateSpeakerViewModel vm,
TimeslotManagementViewModel model)
{
//The idea would be to have TimeslotManagementViewModel model posted back with the set values by the user before "AddSpeaker" was clicked.
}
However with this solution the previous set inputs are lost to the user.
So atm I'm thinking either to use map every property of the TimeslotManagementViewModel to the CreateSpeakerViewModel to pass them between controllers or maybe an Ajax call could work or drop the popup all togheter. Or better yet someone here knows a better option?
Many thanks!
After some trail and error realized the best, maybe only solution comes by using some simple Javascript.
function SaveSpeaker(e) {
var firstname = $('#txtFirstname').val();
var lastname = $('#txtLastname').val();
$.ajax({
url: '/SpeakerAdmin/CreateSpeaker',
dataType: 'Json',
type: "POST",
data: { firstname: firstname, lastname: lastname },
success: function (data, status, jqXHR) {
console.log('success');
if (data.valFirstname == false) {
$('#valFirstname').text('Firstname not complete');
}
if (data.valLastname == false) {
$('#valLastname').val('Lastname not complete')
}
if (data.valSpeaker == true) {
$('#form-modal').modal('hide');
$('#valSpeaker').text('Speaker added');
$('#speakerBox').append(new Option(firstname + " " + lastname, data.speakerID))
}
},
error: function (jqXHR, status, err) {
},
complete: function (jqXHR, status) {
}
});
So instead of posting the form just using an Ajax call to post to the controller and return Json to populate the new select option.
I'm new in coding with ASP.NET Core. I created a CRUD functions in my application and then i decided to change some rules like Create New do not navigate to another tab it will be navigated to a component modal. So I did the steps that it shown in a tutorial but I didn't get a result .
Here's the page :
This is the code in index.cshtml:
#model IEnumerable<PermissionManagement.MVC.Models.Segment>
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="PlaceHolderHere"></div>
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#addSegment" asp-action="_SegmentModelPartial" data-url="#Url.Action("Create")"> Create </button>
And this is the code wrote it in SegmentModelPartial:
#model Segment
<div class="modal fade" id="addSegment">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addSegmentLabel">Modal title</h5>
<button type="button" class="btn-close" data-dismiss="modal" aria-label="Close">
<span>x</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="SName" class="control-label">Nom</label>
<input asp-for="SName" class="form-control" />
<span asp-validation-for="SName" class="text-danger"></span>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group ">
<label asp-for="SRang" class="control-label">Rang</label>
<input asp-for="SRang" class="form-control" />
<span asp-validation-for="SRang" class="text-danger"></span>
</div>
</div>
</form>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-save="modal">Save changes</button>
</div>
</div>
</div>
</div>
This is my code in site.js:
$(function () {
var PlaceHolderElement = $('#PlaceHolderHere');
$('button[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
PlaceHolderElement.html(data);
PlaceHolderElement.find('.modal').modal('show');
})
})
PlaceHolderElement.on('click', '[data-save="modal"]', function (event) {
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var sendData = form.serialize();
$.post(actionUrl, sendData).done(function (data)){
PlaceHolderElement.find('.modal').modal('hide');
})
})
})
And finally this is the controller:
[HttpGet]
public IActionResult Create()
{
Segment seg = new Segment();
return PartialView("_SegmentModelPartial", seg);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Segment segment)
{
_context.Add(segment);
await _context.SaveChangesAsync();
return PartialView("_SegmentModelPartial", segment);
}
I have a partial view that will not show the result that it gets from the controller. This is in ASP.NET Core MVC 2.1.
The base for the code is from here.
Here is the partial view:
#model City
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Grad</h4>
</div>
<div class="modal-body">
<form asp-controller="City" id="TestForm">
<div class="form-group">
<label class="control-label">Name</label>
<input asp-for="Name" class="form-control" id="CityName" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">Postal Code</label>
<input asp-for="PostalCode" class="form-control" id="PostalCode" onkeypress="return isNumberKey(event)" />
<span asp-validation-for="PostalCode" class="text-danger"></span>
</div>
<div class="form-group">
<label class="control-label">Country TEST</label>
<input type="text" id="txtCounty" name="CountyName"/>
<input type="hidden" id="hfCountry" name="CountyID" />
<span asp-validation-for="CountryID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" id="SaveCity" />
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" id="CloseCity" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
The part in question is:
<div class="form-group">
<label class="control-label">Country TEST</label>
<input type="text" id="txtCounty" name="CountyName"/>
<input type="hidden" id="hfCountry" name="CountyID" />
<span asp-validation-for="CountryID" class="text-danger"></span>
</div>
It does not want to show the result it gets.
The jQuery method I use is, it is inside the Index.cshtml scripts:
$(document).on("focus", "#txtCountry", function (e) {
$("#txtCountry").autocomplete({
source: function (request, response) {
$.ajax({
url: '/City/AutoComplete/',
type: "POST",
data: { "prefix": request.term },
success: function (data) {
response($.map(data, function (item) {
return item;
}))
}
});
},
select: function (e, i) {
$("#hfCountry").val(i.item.val);
},
minLength: 1
});
});
When I put this code:
<input type="text" id="txtCounty" name="CountyName"/>
<input type="hidden" id="hfCountry" name="CountyID" />
outside the partial view it shows the searched for thing.
Here is controller for it:
[HttpPost]
public JsonResult AutoComplete(string prefix)
{
var countries = (from country in this._dbContext.Countries
where country.Name.ToLower().Contains(prefix.ToLower())
select new
{
label = country.Name,
val = country.ID
}).ToList();
return Json(countries);
}
Can anybody help I just can not find the answer.
I found the answer.
The text was showing behind the modal, that is way I could not see it.
<style>
.ui-autocomplete {
z-index: 5000;
}
</style>
Put that inside the _Layout.cshtml file, inside the enviroment.
<environment include="Development">
... some stuff...
<style>
.ui-autocomplete {
z-index: 5000;
}
</style>
... some ,oe stuff...
</environment>
There seems to be a couple ways to do it. I really wanted this video to work for me. https://www.youtube.com/watch?v=oHWEs8XWA2U
Searching the web, I found it hard to find this question being asked recently, so I am wondering if newer and improved (easier) ways have been implemented.
Here is my Home controller
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult PartialViewTest()
{
return PartialView();
}
[HttpPost]
public ActionResult PartialViewTest(Person person)
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
Here is my view I want the pop up on
#{
ViewBag.Title = "Contact";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" class="btn-block" style="width:225px">Modal </button>
<div class="modal fade" id="myModal" role="dialog" data-url='#Url.Action("PartialViewTest","Home")'></div>
<script type="text/javascript">
$(document).ready(function () {
$('.btn-block').click(function () {
var url = $('#myModal').data('url');
$.get(url, function (data) {
$("#myModal").html(data);
$("#myModal").modal('show');
});
});
});
</script>
Here is my partial view
<div class="container">
<div class="row">
<div class="col-sm-4"></div>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModal-label">Bootstrap Dialog</h4>
<div>
<div class="modal-body">
<div class="form-group">
<input type="text" placeholder="enter name" class="form-control" id="text" name="text" />
</div>
<div class="form-group">
<input type="text" placeholder="enter name id" class="form-control" id="text" name="text" />
</div>
<div class="form-group">
<input type="text" placeholder="adress" class="form-control" id="text" name="text" />
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" id="btnOK" onclick="">OK</button>
<button class="btn btn-default" data-dismiss="modal" id="btnCancel">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
When I click the button as seen in the image above. Nothing happens. Why doesn't the popup view appear?
If this is not the best way to go about it, could you provide a link to a tutorial for the most professional, proper, and easiest way to accomplish this?
If this is Bootstrap then your partial view's modal HTML is broken. modal-body and modal-footer are under modal-header. I'm pretty sure modal-header, modal-body and modal-footer needs to be direct children of modal-content and that needs to child of modal-dialog and that needs to be child of modal and you have those container divs there wrapping them.
Edit:
Your problem is that you are loading your jquery and bootstrap after you try to use them. That <script> is run before your scripts are loaded. You need to put that into scripts section.
Camilo Terevinto notice you need remove jQuery script tag from your view. You already have jQuery in a bundle.
"When I click the button as seen in the image above. Nothing happens. " -> I have just tried your code and it works, modal is openning. Has Camilo Terevinto comment you should press 12 in chrome, and check for errors in console tab.
After modal open, what is missing in your code?
Use "Person" model in modal, create a post form and set button ok to submit
#model Person //Should contain person model namespace
#Html.BeginForm("PartialViewTest", "Home", FormMethod.Post)
{
<div class="container">
<div class="row">
<div class="col-sm-4"></div>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModal-label">Bootstrap Dialog</h4>
<div>
<div class="modal-body">
<div class="form-group">
#Html.TextBoxFor(p => p.name)
</div>
<div class="form-group">
#Html.TextBoxFor(p => p.adress)
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" id="btnOK" onclick="">OK</button>
<button class="btn btn-default" data-dismiss="modal" id="btnCancel">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
}
Your post action should redirect to Index.
[HttpPost]
public ActionResult PartialViewTest(Person person)
{
/* do things */
return RedirectToAction("Index");
}
I'm trying to rerender the partialview ONLY in my modal, after the ajax request.
But when I get the response everything is rerendered and the only thing showing is the partialview..
PartialView:
#{
var bidModel = new BidModel();
}
<div>
<div class="row">
#if (ViewBag.Message != null)
{
<div class="alert alert-success">#ViewBag.Message</div>
}
</div>
<span class=" alert-danger">
#Html.ValidationSummary()
</span>
<div class="form-group">
<input name="Bidder" asp-for="#bidModel.Bidder" value="#User.Identity.Name" type="hidden" />
<input name="AuctionId" asp-for="#bidModel.AuctionId" type="hidden" id="auctionId" />
<label asp-for="#bidModel.Amount" />
<input name="Amount" asp-for="#bidModel.Amount" />
</div>
</div>
Controller:
public async Task<IActionResult> AddBid(BidModel Bid)
{
var result = await _bidBusinessInterface.CreateBidAsync(Bid, Bid.AuctionId);
if (result)
{
ViewBag.Message = "Bud lagt!";
}
else
{
ViewBag.Message = "Bud förlågt!";
}
return PartialView("_BidCreatorPartial");
}
And then we have the modal where i want to rerender the partialview:
<div class="modal fade" id="bidModal" tabindex="-1" role="dialog" aria-labelledby="bidModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="bidModalLabel">Lägg bud</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form asp-action="AddBid" asp-controller="Home" method="POST" data-ajax="true" data-ajax-update="frmBid">
<div id="frmBid">
<partial name="_BidCreatorPartial" model="#bidModel"/>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Avbryt</button>
<button type="submit" class="btn btn-primary">Spara</button>
</div>
</form>
</div>
</div>
</div>
</div>
As I said, what I want to accomplish is to rerender the form, so that the message can be shown in the modal.
What happens is it renders a whole white page with only the form and the message.
You didn't actually post your form itself, but my best guess is that you're just doing a standard old HTML form post. That's always going to cause the page to change, and then since you're only returning a partial view, and not a full view, your page gets replaced with just that snippet of HTML.
What you want requires AJAX. You need to catch the submit event on the form, and instead of letting it go as normal, you make an AJAX request with the form data serialized. Then, in the success callback of your AJAX request, you'll need to query the element you want to replace the HTML of from the DOM and change its innerHTML value to what's returned from the AJAX request.
Since an ASP.NET Core project comes with jQuery out of the box, I'm going to assume you can use that:
$('#MyForm').on('submit', function (e) {
e.preventDefault();
var $form = $(this);
$.ajax({
url: $form.attr('action'),
method: 'post',
data: $form.serialize(),
success: function (html) {
$('#frmBid').html(html);
}
});
});