Toastr notifications at the redirect from modal window - asp.net

I'm hoping to use Toastr in ASP.net MVC5 with modal windows. Now, when I click the button on modal window, I'm sending data to one of my controllers via AJAX call and get redirected to the home page. Unfortunately, Toastr notifications are not working in this scenario. In dev console I can see the notification when using break points, though. But with redirect it just doesn't have any time to be seeing on the page. Any suggestions how to make it stay and be visible at the redirect to another page? I'm using Toastr in .done and .fail methods of the AJAX call.
The modal window in the html file:
<div class="modal fade" id="myConfirmModal" 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-hidden="true">×</button>
</div>
<div id="WorkflowConfirmModal" class="modal-body">
Are you sure you want to submit this transaction?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="myID" data-val="#Url.Action("myAction", "myController", null)" data-redirect="#Url.Action("Index", "Home")">Yes</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
The AXAJ call in the separate .js file:
$('#myID').on("click", function () {
var reviewData = {
//... my data here
};
$.ajax({
url: $('#myID').data('val'),
type: 'POST',
dataType: 'json',
data: reviewData,
success: function (data) {
if (data.success == true) {
window.location.href = $('#myID').data('redirect');
} else {
$('#myConfirmModal').modal('hide');
bootbox.alert(
"<h4>Submit Errors</h4>" +
"<hr><p>" + data.errors + "</p>");
}
}
})
.done(function () {
toastr.success("Success!");
})
.fail(function () {
toastr.error("Something went wrong.");
});
});

Your browser is off to the races when you issue that window.location command so you have two options:
Route a value ALLLL the way through your controller back into your reloaded view and kick the toastr off there. (This sucks, don't do this)
Restructure your JS so that your window.location call happens after the toastr hide event finishes. something like so :
toastr.error("Content", "Title", {onHidden : function() { alert("do a redirect inside this function");}});
chained Example for first time poster:
var n = $('#n').val();
$('#success').click(function () {toastr.success( $('#g').val(), n, { onHidden : function() { toastr.warning( $('#l').val(), n, { onHidden : function() { toastr.error( $('#r').val(), n, {onHidden : function() { alert( $('#d').val());}, "timeOut": "900"});}, "timeOut": "900"});}, "timeOut": "900"}); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css"><input type="hidden" id="n" value="Never Gonna"><input type="hidden" id="g" value="give you up"><input type="hidden" id="r" value="run around"><input type="hidden" id="l" value="let you down"><input type="hidden" id="d" value="and desert you">
<input type="button" value="Click Me" id="success" />
Example for first option requested by user:
View where BTN is pushed (just append a query string param when you call the controller action - here I am just sending a request to HOME/Index and appending ConfirmS = true as a param):
<div class="btn btn-primary" onclick="location='/?ConfirmS=true'"> GO </div>
Home Controller Index Action method (add a nullable param and if it exists and is true in this case then set a viewbag param to send to our view)
public ActionResult Index(bool? ConfirmS)
{
if (ConfirmS.HasValue && ConfirmS.Value) { ViewBag.ConfirmSubmitMessage = "weeeee"; }
return View();
}
Home Index View (check if your viewbag property exists and if it does then do something like trigger a toastr alert):
#if (ViewBag.ConfirmSubmitMessage != null)
{
<script>alert('#ViewBag.ConfirmSubmitMessage');</script>
}

My final code. The modal window in the html file:
<div class="modal fade" id="myConfirmModal" 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-hidden="true">×</button>
</div>
<div id="WorkflowConfirmModal" class="modal-body">
Your text goes here.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="myID" data-val="#Url.Action("myAction", "myController", null)" data-redirect="#Url.Action("Index", "Home", new { ConfirmToastr = true})">Yes</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
The Home Controller/Index Method:
public ViewResult Index(bool? ConfirmToastr)
{
if (ConfirmToastr.HasValue && ConfirmToastr.Value) { ViewBag.ConfirmSubmitMessage = "Foo"; }
return View("Index");
}
The Index.cshtml of Home/Index(). I'm using CDNs here but local taostr.js and taostr.css will do the trick:
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
#if (ViewBag.ConfirmSubmitMessage != null)
{
<script type="text/javascript">
$(function () {
toastr.success("Success.", "Thanks.", {
timeOut: 3000,
onHidden: function () {
window.history.pushState("Name", "Title", "#Url.Action("Index", "Home")");
}
});
});
</script>
}
The AXAJ call in the separate .js file:
$('#myID').on("click", function () {
var reviewData = {
//... your data here
};
$.ajax({
url: $('#myID').data('val'),
type: 'POST',
dataType: 'json',
data: reviewData,
success: function (data) {
if (data.success == true) {
window.location.href = $('#myID').data('redirect');
} else {
$('#myConfirmModal').modal('hide');
bootbox.alert(
"<h4>Submit Errors</h4>" +
"<hr><p>" + data.errors + "</p>");
}
}
})
});

Related

Multiple submit button fail to find the handler method in asp.net core 3.1 razor page application

I have a single form which has two button one to upload image using ajax call & other is main submit button which saves all the data.
I am still very new to asp.net core and trying different thing to learn asp.net core with razor page.
I read lot of article about multiple form submit but most of then where using two form with submit button for each.
My issue is when i hit the submit button it fails to find the handler method, after full days troubleshoot nothing worked and last few article point to error/failure to antiforgery, i not sure how to implement it in below code as i tried few but they gave error may be article where old referencing core 2.2 etc example1 example2
I am not sure about the what exactly is causing the issue any help would be appreciate.
I am trying to upload Image using Ajax method in asp.net core Razor pages, I am main form in will all input fields are kept and with the form for Fileupload i am also added addition button which is for file upload using Ajax, When i hit the
<input type="submit" value="Upload Image" asp-page-handler="OnPostUploadImage" id="btnUploadImage" />
i want it to call OnPostUploadImage method in pageModel file but it alway goes to default OnPost method. when i rename the OnPost to OnPost2 nothing happend..
How can i call OnPostUploadImage() on button btnUploadImage click event.
When i hit click btnUploadImage it generates following error on browser console
Error in FF
XML Parsing Error: no root element found Location:
https://localhost:44364/Admin/News/NewsCreate?handler=OnPostUploadImage
Line Number 1, Column 1:
Error in Chrome
jquery.min.js:2 POST
https://localhost:44364/Admin/News/NewsCreateMultipleSubmit?handler=OnPostUpLoadImage
400 (Bad Request)
event though path looks fine but it cant find it as per error message
#page
#model BookListRazor.Pages.Admin.News.NewsCreateModel
#{
ViewData["Title"] = "News Create";
Layout = "~/Pages/Shared/_LayoutAdmin.cshtml";
}
<div class="border container" style="padding:30px;">
<form method="post" enctype="multipart/form-data">
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<input hidden asp-for="News.NewsImage" />
<input id="fileName" hidden value="" />
<div class="form-group row">
<div class="col-2">
<label asp-for="News.NewsHeading"></label>
</div>
<div class="col-10">
<input asp-for="News.NewsHeading" class="form-control" />
</div>
<span asp-validation-for="News.NewsHeading" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-2">
<label asp-for="News.NewsImage"></label>
</div>
<div class="col-10">
#*<input asp-for="News.NewsImage" type="file" class="form-control" id="NewsImage">*#
#*Photo property type is IFormFile, so ASP.NET Core automatically creates a FileUpload control *#
<div class="custom-file">
<input asp-for="NewsImageForUpload" class="custom-file-input form-control">
<label class="custom-file-label">Click here to change photo</label>
<input type="submit" value="Upload Image" asp-page-handler="OnPostUploadImage" id="btnUploadImage" />
</div>
</div>
<span id="imageStatus" class="text-danger"></span>
<span asp-validation-for="NewsImageForUpload" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-3 offset-3">
<input id="btnSave" type="submit" value="Create" class="btn btn-primary form-control" />
</div>
<div class="col-3">
<a asp-page="Index" class="btn btn-success form-control">Back to List</a>
</div>
</div>
</form>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="https://cdn.ckeditor.com/4.14.0/full/ckeditor.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
$(document).ready(function () {
$("#btnSave").addClass("disable-button");
$('.custom-file-input').on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).next('.custom-file-label').html(fileName);
$("#fileName").val(fileName);
$("#btnSave").removeClass("disable-button");
});
if ($("#fileName").val() == "") {
//alert("Select Image...");;
}
});
</script>
</div>
#section Scripts{
<partial name="_ValidationScriptsPartial" />
<script>
$(function () {
$('#btnUploadImage').on('click', function (evt) {
console.log("btnUploadImage");
evt.preventDefault();
console.log("btnUploadImage after evt.preventDefault()");
$.ajax({
url: '#Url.Page("", "OnPostUploadImage")',
//data: new FormData(document.forms[0]),
contentType: false,
processData: false,
type: 'post',
success: function () {
alert('Uploaded by jQuery');
}
});
});
});
</script>
}
.cs file CODE
public async Task<IActionResult> OnPost()
{
if (ModelState.IsValid)
{
return Page();
}
else
{
return Page();
}
}
public IActionResult OnPostUploadImage()
{
//Some code here
}
Verify that you add the following code to the ConfigureServices method of startup.cs:
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
If you want to enter the OnPostUploadImage method, the url of the Ajax request needs to be changed to #Url.Page("", "UploadImage") without adding OnPost.
And the Ajax request should send the anti-forgery token in request header to the server.
Change your ajax as follow:
#section Scripts{
<partial name="_ValidationScriptsPartial" />
<script>
$(function () {
$('#btnUploadImage').on('click', function (evt) {
console.log("btnUploadImage");
evt.preventDefault();
console.log("btnUploadImage after evt.preventDefault()");
$.ajax({
url: '#Url.Page("", "UploadImage")',
//data: new FormData(document.forms[0]),
contentType: false,
processData: false,
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
type: 'post',
success: function () {
alert('Uploaded by jQuery');
}
});
});
});
</script>
}
You can refer to this for more details.

Update portion of the website using Ajax form call

I am trying to show an error message when there is an error when performing a POST form request using Ajax (I don't want the page to refresh). However, the code bellow does not change - it still shows "NO ERRORS" although the TempData["Error] variable is not null (it's set in the controller's action). What I am doing wrong?
That is my _Layout.cshtml (I want to be able to show this error message from every page)
<!DOCTYPE html>
<html>
#*#RenderBody()*#
<head>
</head>
<body>
<div id="divEmp">
#if (TempData["Error"] != null)
{
<div class="alert alert-danger" role="alert">"Error here"</div>
}
else
{
<div class="alert alert-success" role="alert">NO ERRORS</div>
}
</div>
#RenderSection("BodyFill", false)
#RenderBody()
#RenderSection("Scripts", required: false)
</body>
</html>
That is my Controller
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ShareWorkbook(string emails, string title, string id, string queryBuilderId)
{
TempData["Error"] = Res.System_Error_Message;
return NoContent();
}
That is my form (it's located in a partial view and injected at runtime in the main page)
#using DNAAnalysisCore.Resources
#model DNAAnalysisCore.Models.WorkbookShareModel
#* Partial view that contains the 'Share Workbook dialog' modal *#
<!-- Modal -->
<div onclick="activateShareButtons()" class="modal fade" id="shareFormModal" role="dialog">
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Share Workbook - #Model.Title</h4>
</div>
<form id="partialform" asp-action="ShareWorkbook" asp-controller="Home" method="post" data-ajax="true" data-ajax-update="divEmp">
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
<button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
You can directly modify the HTML markups using javascript in callback function of Ajax .I assume in your _Layout.cshtml :
<div id="divEmp">
<div id="showError" style="display:none;" class="alert alert-danger" role="alert">"Error here"</div>
<div id="noError" style="display:none;" class="alert alert-success" role="alert">NO ERRORS</div>
</div>
In your page you will use ajax to call server side function , and depend on response you can directly show/modify above area :
$(function () {
$.ajax({
type: "POST",
url: '/Home/GetJobData',
contentType: 'application/json; charset=utf-8',
success: function (response) {
if (response.success) {
$("#showError").hide();
$("#noError").show();
}
else {
$("#showError").show();
$("#noError").hide();
$("#showError").text(response.responseText);
}
},
error: function (response) {
alert("error!");
}
});
})
Server side function :
public IActionResult GetJobData()
{
var isFileSupported = true;
if (!isFileSupported)
{
// Send "false"
return Json(new { success = false, responseText = "Your operation fail !" });
}
else
{
// Send "Success"
return Json(new { success = true, responseText = "Your operation Success !" });
}
}

get id from datatable and show his results into a modal ASP SQL

I have a datatable in an aspx page connected to an mssql database, I added a column with a button to open the modal in which I would like to show the results for the selected record. How do I pass the record id and run a sql query to show the fields that interest me?
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$('#dt1').DataTable({
"processing" : true,
"ajax" : {
"url" : "selectbasic.aspx",
dataSrc : ''
},
"columns" : [
{
"data": "ID",
},
{
"data" : "Name"
},
{
"data" : "Email"
},
{
"data" : "Address"
}, {
"data" : "UserType",
"render": function(data, type, row, meta){
if(type === 'display'){
if(data=="0"){
data="NO";
}else
{
data="SI";
}
data = data;
}
return data;
}
},
{ data : 'edit',
render : function(data, type, row) {
return '<center><a data-toggle="modal" data-target="#modaldetails"><i class="glyphicon glyphicon-edit"></i></a></center>'
}
},
]
});
</script>
<div class="modal fade" id="modaldetails" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
<div class="modal-dialog" style="z-index: 100;">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="exampleModalLongTitle">Edit</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
"show results here where ID=...."
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
In practice I would like to do what with php & mysql is done using $ _GET ['ID'] and mysql_fetch_assoc (), but in asp & mssql. Thank you
Do something like this:
$('#YourTable tbody').on( 'click', 'a', function () {
var data = '';
data = YourTable.row( $(this).parents('tr') ).data();
//to do this your table need to be declared like this
//yourTable= $('#YourTable').DataTable();
console.log(data);
var carId= data['id'];
console.log(carId);
})
if you have any issue check this post where i answered something similar JQ event didnt active on the extract row sort by datatable.js

Asp.net MVC 5 Ajax call modal dialog

I am new to asp.net MVC 5, I wonder how to use Ajax to call the modal with partial view? i had tried some code but the modal doesn't show up. Any body help?
Here is my code:
View
<script>
#Scripts.Render("~/bundles/jqueryval")
// Create
$(".modalCreate").click(function (e) {
e.preventDefault();
$.ajax({
cache: false,
type: "GET",
url: '#Url.Action("Create","Category")',
success: function () {
$(this).attr('data-target', '#createCat');
$(this).attr('data-toggle', 'modal');
// Attach listener to .modal-close-btn's so that when the button is pressed the modal dialog disappears
$('body').on('click', '.modal-close-btn', function () {
$('#createCat').modal('hide');
});
//clear modal cache, so that new content can be loaded
$('#createCat').on('hidden.bs.modal', function () {
$(this).removeData('bs.modal');
});
$('#CancelModal').on('click', function () {
return false;
});
// Init JQuery Validation for view
$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");
},
error: function (xhr, ajaxOptions, thrownError) {
displayAjaxError(thrownError);
}
});
});
</script>
<p>
#Html.ActionLink("Create Category ", "Create", "Category",
null, new { #class = "modalCreate btn btn-success" })
</p>
<div id="createCat" class="modal fade"
tabindex="-1" role="dialog">
<div class="modal-content">
</div>
</div>
This is my controller:
public ActionResult Create()
{
return PartialView("_Create");
}
// POST: /Category/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CategoryCreateVM productcategory)
{
if (ModelState.IsValid)
{
ProductCategory cat = Mapper.Map<CategoryCreateVM, ProductCategory>(productcategory);
db.ProductCategories.Add(cat);
db.SaveChanges();
TempData["Message"] = "New Category added sucessfully.";
ViewBag.Message = "New Category added sucessfully.";
return RedirectToAction("Index");
}
return PartialView(productcategory);
}
and partial view:
<div class="modal-dialog">
<div class="modal-body">
<div class="modal-content">
#using (Html.BeginForm("Create", "Category", FormMethod.Post))
{
}
</div>
</div>
</div>
I using the boostrap default theme to do. I try to debug in browser inspection it doesnt show any error. But I can sure is it able to find my partial view but the modal never show up. I hope that anyone can help me check my code.
if I understand well this is the way:
1- add your Modal Template in "<script>" part of Views->Shared->_Layout whith specific id for each part of modal to use it every where you want, for example:
<!-- Modal start-->
<div class="modal fade" id="Modalid" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"></button>
<h4 class="modal-title" id="ModalLabelid">Modal title</h4>
</div>
<div class="modal-body" id="ModalBodyid"></div>
</div>
</div>
</div>
<!--Modal End-->
2- then add code below in any view that you want use modal :
<script>
function functionname() {
$("#Modalid").modal();
$("#ModalLabelid").html("YourTitle");
$("#ModalBodyid").load("url of partial view or anything that you want show in modal body");
}
</script>
now if you want load body of modal from some partialview , write the url in .load() method :
$("#ModalBodyid").load("/Controller/Action/");
and if your action should get parameter, add the name of parameter exactly as in action entire :
$("#ModalBodyid").load("/Controller/Action/" + NameOfParameterinAction);
finally to use your script you should call functionname() every where you need from any View :)

Ui-bootstrap-modal with ui-bootstrap-tpls-0.13 and bootstrap 3.3.2, angular 1.3.14 not working

As mentioned in the title, the modal does not show up.
The content of the form is loaded via formly and the content of the template seems to load, but it only shows the modal very thin, with the overlay but not the content.
I have a main controller in which I have:
$scope.add = function(){
$modal.open({
templateUrl: 'app/js/templates/popupAddCarForm.html',
controller: 'FormsController',
controllerAs: 'vm',
backdrop: 'static',
resolve: {
formData: function(){
return {
fields: getFormFields(),
model: {}
}
}
}
});
};
My html is like so:
<script type="text/ng-template" id="popupAddCarForm">
<div class="modal">
<div class="modal-dialog">
<div class="modal-header">
<h3 class="modal-title">Adauga masina</h3>
</div>
<div class="modal-body">
<form name="vm.addCarForm">
<formly-form model="vm.formData.model" fields="vm.formData.fields">
</formly-form>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="submit" >Adauga</button>
</div>
</div>
</div>
And my form controller like so:
davidintercar.controller('FormsController',
function($modalInstance, formData) {
var vm = this;
//debugger;
vm.formData = formData;
vm.originalFields = angular.copy(vm.formData.fields);
}
);
The result is like so:
LATER EDIT:
In order to rid ourselfes of other doubts, here is the code from the demo:
app.controller('ModalInstanceCtrl', function ($modalInstance, formData) {
var vm = this;
debugger;
// function assignment
vm.ok = ok;
vm.cancel = cancel;
// variable assignment
vm.formData = formData;
vm.originalFields = angular.copy(vm.formData.fields);
// function definition
function ok() {
$modalInstance.close(vm.formData.model);
}
function cancel() {
$modalInstance.dismiss('cancel');
};
});
Link: angular-formly.com/#/example/integrations/ui-bootstrap-modal
LATER, LATER EDIT:
Plunker: http://plnkr.co/edit/8wgL4t2oXsFFeLBKGGW8?p=preview
Folder Structure:
--app
----js
------controller
------services
------templates
------view
----app.js
intex.html
My popupAddCarForm.html is in the templates directory, but as you see in the plunker, it does not render my loaded content, even in the same directory although a separate template file.
The modal template don't need to have the modal and modal-dialog layer - they will be generated by bootstrap.
<script type="text/ng-template" id="popupAddCarForm.html">
<div class="modal-header">test
<h3 class="modal-title">Adauga masina</h3>
</div>
<div class="modal-body">
<form name="vm.addCarForm">
<formly-form model="vm.formData.model" fields="vm.formData.fields">
</formly-form>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="submit" >Adauga</button>
</div>
</script>

Resources