In my application I was using simple View the Validation, both client and server side validation, was working fine, but now I have changed to bootstrap modal and PartialView. The problem is that Client Side Validation dosn't work any more and for server side validation when I click submit he redirect me to new page (see picture) instead of showing the error on the current modal pop-up.
Create Controller :
[HttpGet]
public ActionResult Create()
{
ViewBag.CAT_ID = new SelectList(db.CATEGORIE, "CAT_ID", "LIBELLE");
ViewBag.C_GARANT = new SelectList(db.GARANTIE, "C_GARANT", "LIB_ABREGE");
return PartialView("_Create");
}
//
// POST: /Taux/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(TAUX taux)
{
if (ModelState.IsValid)
{
db.TAUX.Add(taux);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CAT_ID = new SelectList(db.CATEGORIE, "CAT_ID", "LIBELLE", taux.CAT_ID);
ViewBag.C_GARANT = new SelectList(db.GARANTIE, "C_GARANT", "LIB_ABREGE", taux.C_GARANT);
return PartialView("_Create", taux);
}
_Create Partial View :
#model pfebs0.Models.TAUX
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="CreateTaux">Add</h3>
</div>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="modal-body">
<div class="form-group">
<div class="form-group">
<label for="Categorie">Categorie : </label>
#Html.DropDownList("CAT_ID", String.Empty)
#Html.ValidationMessageFor(model => model.CAT_ID)
</div>
//Other Form input.
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default">Submit</button>
</div>
}
</div>
<script>
$("select").addClass("form-control");
$("input").addClass("form-control");
$("label").addClass("control-label");
</script>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval") }
Index View where I puted the modal :
<p>
#Html.ActionLink("Ajouter", "Create", "Taux",
new { id = "btnAdd", #class="btn btn-default"})
</p
<div id="modalDiv" class="modal fade" >
<div class="modal-dialog">
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(function () {
$.ajaxSetup({ cache: false });
$('#btnAdd').click(function () {
$('.modal-dialog').load(this.href, function () {
$('#modalDiv').modal({
backdrop: 'static',
keyboard: true
}, 'show');
});
return false;
});
});
</script> }
So what I have to add or change to Have client validation in my modal and for server validation to be redirected to modal, instead new page like in picture ?
You can rely on the built in bootstrap functionality of the role and data-target attributes. If you define your modal's role as "dialog" and give it an id then you can reference that in a HTML button with a data-target and data-toggle attributes.
You also need to avoid loading your _Create partial from an ajax request. Just load it along with Index using #Html.Partial. It will not appear in your view if the attributes are set correctly.
Here are the steps I did to get it working:
First modify your _Index to load partial view and update your modalDiv to define a role.
<div class="modal fade" id="modalDiv" tabindex="-1" role="dialog" aria-hidden="true">
#Html.Partial("~/{PathToView}/_Create.cshtml", new pfebs0.Models.TAUX())
</div>
Now instead of using #HtmlActionLink and JavaScript to load dialog, create a button as follows. Make sure to remove the JS click event code.
<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#modalDiv">Ajouter</button>
Now bootstrap will handle showing and hiding dialog automatically with the defined role and data attributes and MVC validation will appear correctly. You can leave your controller code as-is.
Related
I have books retrieved from database in the Index view. Each one has a button below. When you click them a modal box should pop up with the corresponding book details (book img, name title, decsription, price etc) printed on it.
Index View:
<!-- language: lang-html -->
#model AuthorTest.Models.HomeModel
<!--razor codes where book properties are called-->
#foreach(var book in Model.Bestsales)
{
<a class="first__img" href="single-product.html"><img src="~/Uploads/img/#(book.Id + " .jpg ")"</a>
<h4>product.html">#book.Name</a></h4>
<ul class="prize d-flex">
<li>#book.Price</li>
</ul>
<!--modal-box pop-up button-->
<a data-toggle="modal" title="Quick View" data-id="#book.Id" class="modal-open" href="#productmodal"><i class="bi bi-search"></i></a>
}
I'm trying to pass a book id using ajax
<!-- language: lang-js-->
#section scripts{
<script>
$(".modal-open").click(function () {
var id = $(this).data("id");
$.ajax({
type: "POST",
url: "/Home/Details/" + id
});
});
</script>
}
into the "Details" action that retrieves related book and returns it to a view where modal box content is placed.
<!-- language: lang-cs-->
[HttpPost]
public ActionResult Details(int id)
{
HomeModel model = new HomeModel();
var book = db.Books.Where(b => b.Id == id).Include(b => b.Author).SingleOrDefault();
if (book == null)
{
HttpNotFound();
}
book.DisplayNumber++;
db.SaveChanges();
model.bookDetails = book;
return view( model);
}
This is the HomeModel class that I use to keep two models 1)list property of type Book to loop through my books in the Index view
2)property of Book type to call model-related book datas in "Details" view:
<!-- language: lang-cs-->
public class HomeModel
{
public List<Book> BestSales { get; set; }
public Book bookDetails { get; set; }
}
a view where modal box content is placed:
<-- language: lang-html-->
#model AuthorTest.Models.HomeModel
div id="quickview-wrapper">
<!-- Modal -->
<div class="modal fade" id="productmodal" tabindex="-1" role="dialog">
<div class="modal-dialog modal__container" role="document">
<div class="modal-content">
<div class="modal-header modal__header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="modal-product">
<!-- Start product images -->
<div class="product-images">
<div class="main-image images">
<img alt="big images" src="~/Uploads/img/#(Model.bookDetails.Id + ".jpg")">
</div>
</div>
<!-- end product images -->
<div class="product-info">
<h1>#Model.bookDetails.Name</h1>
<div class="rating__and__review">
</div>
<div class="price-box-3">
<div class="s-price-box">
<span class="new-price">#Model.bookDetails.Price</span>
<span class="old-price">$34.00</span>
</div>
</div>
<div class="quick-desc">
#Model.bookDetails.Description
</div>
<div class="addtocart-btn">
Add to cart
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
When I click modal-open button the id gets passed to the "Details" action, corresponding book is retrieved and takes me to the view. But it seems like modal box pops up before ajax runs action and therefore the data is not printed. Where do I make mistake? How to pass the book details into the modal-box correctly?
An Ajax call is asynchronous, so you must get in this mindset: when you work in a non sync way, you shall manage async calls with callbacks. jQuery offers different types of callback for the $.ajax() method, such as "success","error".... on and on. If the ajax call results in a server exception for instance, the HTTP result will be 500 and you can manage it in the "error" callback subscribing the callback with a your custom method that will be raised by jQuery. On the other way, the success callback must be subscribed by a method that accepts parameters where will be the server response (in this case, an html response). So, if the result is a success (HTTP Status code 200), you will have the HTML in that parameter, and you can use it to append in your modal (always with jQuery methods... or even in simple javascript if you like more)
Take a look to callbacks subscriptions:http://api.jquery.com/jquery.ajax/ in the "Callback Function Queues" section. You will find out that I gave you just a real basic explanation and there's a lot of more to learn!
I want to try to implement this with Ajax post request, but I've never used Ajax and I'm not sure how to go about doing this.
My view code for password panel look's like this:
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Reset Password</h3>
</div>
<div class="panel-body" id="myForm">
#using (Html.BeginForm("EditPassword", "Users", new { UserId = Model.User.Id, Token = Model.Token }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label"})
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control", #type = "text" })
</div>
</div>
<div id="dialog-modal" style="display:none;" title="Basic modal dialog"></div>
<div class="col-md-9">
<button type="submit" data-toggle="modal" data-target=".bootstrapmodal" class="btn btn-primary" value="Reset" onclick="javascript: return checkPassForm(document.getElementById('myForm'));">Reset</button>
</div>
}
</div>
Bootstrap Modal code:
<div class="modal fade bootstrapmodal" id="modalMain" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="false" data-keyboard="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button data-dissmiss="modal" class="close modal-close-btn" data-dismiss="modal" aria-hidden="true"> <span>×</span> </button>
<div class="modal-title"><h3>News Letter Account</h3></div>
</div>
<div class="modal-body">
<p>This is a newsletter only account which does not have an existing password.</p>
<p>Do you wish to create a mySewnet account for this user?</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" id="btn-updateNL"> Continue </button>
<button class="btn btn-default cancel-modal" data-dismiss="modal" aria-hidden="true"> Cancel</button>
</div>
</div>
</div>
</div>
Script code in the same view looks as follows
#Scripts.Render("~/bundles/jquery")
<script type="text/javascript">
$(document).ready(function () {
$("#btn-updateNL").on('click', function (e) {
#this.Model.User.NewsletterOnly.Equals(false);
});
});
The controller code for View's reset password panel:
[AllowAnonymous]
[HttpGet]
public ActionResult EditPassword(int userId, string token)
{
User user = new User();
EditUserViewModel top = new EditUserViewModel();
int rer = top.UserId;
userId = user.Id;
token = UserManager.GeneratePasswordResetToken(user.Id);
var model = new EditUserViewModel()
{
UserId = userId,
Token = token
};
return RedirectToAction("Edit", new { userId = userId });
}
//POST: /Admin/UserManager/Edit
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EditPassword(EditUserViewModel model)
{
model.Token = UserManager.GeneratePasswordResetToken(model.UserId);
var user = this.UserManager.FindById(model.UserId); //Gets current user
var oldTermsAndConditionAgreement = user.TermsAndConditionsAgreement; //Gets current value of TermsAndConditionsAgreement
user.TermsAndConditionsAgreement = true; //Sets TermsAndConditionsAgreement to true
//Run a break on this line next time when coding
var result = this.UserManager.ResetPassword(model.UserId, model.Token, model.Password.Trim()); //If TermsAndConditionsAgreement is not true, this seems to break
user.TermsAndConditionsAgreement = oldTermsAndConditionAgreement; //TermsAndConditionsAgreement is set back to original value after process runs
if (result.Succeeded)
{
TempData["Message"] = AppResources.Common.FormAdminPasswordresetSuccess;
//return RedirectToAction("Login", "Account");
await _db.SaveChangesAsync();
//return RedirectToAction("Edit");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error);
}
return RedirectToAction("Edit", new { id = model.UserId });
}
I want to give 'Reset' button on the password panel the ability to display model panel if user has "newsletteronly" check-box set to "true".Which I can do by placing this Razor if statement syntax around modal code above.
*when Newsletteronly is set to true and checked account is not really a account so admin can't reset user's password, because no password is created in database for users who choose to receive news-letter. Other data like email, name, street address are collected and stored in DB. Email is username in this web-application.
#if (this.Model.User.NewsletterOnly == true)
{}
Doing this only allows the modal to display when reset button is clicked and if user's account meet the condition. The issue I'm having now is in trying to get
model to update for "NewsletterOnly" value to false when 'Continue' button is clicked on modal dialog after page-loads and modal disappears. I believe Ajax post can resolve this but don't know how to implement this with bootsrap modal on MVC 5 Razor .Net.
Images:
("Page View") description:Left side of view is "user panel" it displays 'NewsletterOnly' checkbox and it is checked as True if user has a news letter only account) Right side displays reset password panel and other panels
Modal
$("#btn-updateNL").on('click', function (e) {
$.post("yourActionMethodToUpdateNewsLetterValue",{userId:1,NL:false},function(){
alert('updated succesully');
});
});
where {userId:1,NL:false} here you need to pass the current users Id and then pass the value for NewsLetterOnly variable ie: NL as false. You can have a controller method which accepts these two parameters and then write your logic to update the Db.
Controller Action method would be something like
public async UpdateUserNewsLetterFlag(int userId,bool NL)
I have the following link and I'm trying to load a bootstrap modal when its clicked but the javascript function doesnt seem to be firing. Instead of the view loading inside a modal, its loading as a new page?
#*this is the modal definition*#
<div class="modal hide fade in" id="report-summary">
<div id="report-summary-container"></div>
</div>
<script >
$('a.js-report-summary').click(function (e) {
var url = $(this).attr('href'); // the url to the controller
e.preventDefault();
$.get(url, function (data) {
$('#report-summary-container').html(data);
$('#report-summary').modal('show');
});
});
</script>
public ActionResult ReportSummary()
{
// some actions
return PartialView("ReportSummary", viewmodel)
}
// Report summary view which contains modal
<div class="modal-dialog" role="document">
<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">#ViewBag.FormName - Analysis</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">
Close</button>
</div>
</div>
</div>
There are no errors showing in the console either so why isn't the jquery function firing?
in your click function, add parameter e this will stand for event
then in the function itself add e.preventDefault() This will stop the refreshing effect.
on your controller method try
public ViewResult ReportSummary()
{
// some actions
if(Request.IsAjaxRequest())
return PartialView("ReportSummary", viewmodel);
else
return View("ReportSummary", viewmodel);
}
on your view
$('#exampleModal').on('show.bs.modal', function (event) {//give your model wrapper an id
//do some ajax and get html
$.ajax({
url:'',
success:function(data){
$('#report-summary-container').html(data);
}
});
})
on your anchor tag, add data-toggle="modal" data-target="#exampleModal"
if you dont want to use bootstrap events trigger your modal with
$('#myModal').modal('show')
I'm trying to show a modal from bootstrap 3(here) in my MVC application.
This is what i've done
#model DatePicker.Models.ViewModels.Appointment.CreateAppointmentSelectPersons
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
<link href="~/Content/themes/base/minified/jquery-ui.min.css" rel="stylesheet"/>
}
<button id="showDetail" class="btn btn-default">Next>></button>
<div id="appointmentModal" class="modal hide fade in" data-url="#Url.Action("Detail", "Appointment", new { appointmentId = Model.AppointmentId })">
<div id="appointmentContainer"></div>
</div>
#section Scripts{
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/Scripts/jquery-ui-1.10.4.min.js")
#Scripts.Render("~/Scripts/bootstrap.min.js")
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script type="text/javascript">
$("#showDetail").click(function () {
var url = $("#appointmentModal").data('url');
$.get(url, function (data) {
$('#appointmentContainer').html(data);
$('#appointmentModal').modal(show);
});
})
</script>
}
and in partial view
#model DatePicker.Models.ViewModels.Appointment.DetailsAppointment
<div class="modal fade" id="appointmentModal" tabindex="-1" role="dialog" aria-labelledby="appointmentModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="appointmentModalLabel">Details</h4>
</div>
<div class="modal-body">
<h5>Your appointment is ready to be sent, please reveiew the details</h5>
<dl class="dl-horizontal">
<dt>Subject/Name</dt>
<dd>#Model.Name</dd>
</dl>
</div>
<div class="modal-footer">
<button class="btn btn-primary">Confirm</button>
</div>
</div>
</div>
</div>
and in controller
public ActionResult Detail(Guid appointmentId)
{
....
return PartialView(appointmentDetails);
}
Here, when I click the Next>> button in view, my modal doesn't show.
but when I inspect the network part and see the preview section i can see that the data is being collected from my backend. Its just that modal is not showing.
What should i do?
Edit1:
Console error
You made an error in JavaScript function. It should be like following:
$("#showDetail").click(function () {
var url = $("#appointmentModal").data('url');
$.get(url, function (data) {
$('#appointmentContainer').html(data);
$('#appointmentModal').modal('show');
});
})
The change is: modal(show) to modal('show')
I was looking to using the Twitter Bootstrap Modal windows as a partial view. However, I do not really think that it was designed to be used in this fashion; it seems like it was meant to be used in a fairly static fashion. Nevertheless, I think it'd be cool to be able to use it as a partial view.
So for example, let's say I have a list of Games. Upon clicking on a link for a given game, I'd like to request data from the server and then display information about that game in a modal window "over the top of" the present page.
I've done a little bit of research and found this post which is similar but not quite the same.
Has anyone tried this with success or failure? Anyone have something on jsFiddle or some source they'd be willing to share?
Thanks for your help.
Yes we have done this.
In your Index.cshtml you'll have something like..
<div id='gameModal' class='modal hide fade in' data-url='#Url.Action("GetGameListing")'>
<div id='gameContainer'>
</div>
</div>
<button id='showGame'>Show Game Listing</button>
Then in JS for the same page (inlined or in a separate file you'll have something like this..
$(document).ready(function() {
$('#showGame').click(function() {
var url = $('#gameModal').data('url');
$.get(url, function(data) {
$('#gameContainer').html(data);
$('#gameModal').modal('show');
});
});
});
With a method on your controller that looks like this..
[HttpGet]
public ActionResult GetGameListing()
{
var model = // do whatever you need to get your model
return PartialView(model);
}
You will of course need a view called GetGameListing.cshtml inside of your Views folder..
I do this with mustache.js and templates (you could use any JavaScript templating library).
In my view, I have something like this:
<script type="text/x-mustache-template" id="modalTemplate">
<%Html.RenderPartial("Modal");%>
</script>
...which lets me keep my templates in a partial view called Modal.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<div>
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>{{Name}}</h3>
</div>
<div class="modal-body">
<table class="table table-striped table-condensed">
<tbody>
<tr><td>ID</td><td>{{Id}}</td></tr>
<tr><td>Name</td><td>{{Name}}</td></tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<a class="btn" data-dismiss="modal">Close</a>
</div>
</div>
I create placeholders for each modal in my view:
<%foreach (var item in Model) {%>
<div data-id="<%=Html.Encode(item.Id)%>"
id="modelModal<%=Html.Encode(item.Id)%>"
class="modal hide fade">
</div>
<%}%>
...and make ajax calls with jQuery:
<script type="text/javascript">
var modalTemplate = $("#modalTemplate").html()
$(".modal[data-id]").each(function() {
var $this = $(this)
var id = $this.attr("data-id")
$this.on("show", function() {
if ($this.html()) return
$.ajax({
type: "POST",
url: "<%=Url.Action("SomeAction")%>",
data: { id: id },
success: function(data) {
$this.append(Mustache.to_html(modalTemplate, data))
}
})
})
})
</script>
Then, you just need a trigger somewhere:
<%foreach (var item in Model) {%>
<a data-toggle="modal" href="#modelModal<%=Html.Encode(item.Id)%>">
<%=Html.Encode(item.DutModel.Name)%>
</a>
<%}%>
I have achieved this by using one nice example i have found here.
I have replaced the jquery dialog used in that example with the Twitter Bootstrap Modal windows.
Complete and clear example project
http://www.codeproject.com/Articles/786085/ASP-NET-MVC-List-Editor-with-Bootstrap-Modals
It displays create, edit and delete entity operation modals with bootstrap and also includes code to handle result returned from those entity operations (c#, JSON, javascript)
I use AJAX to do this. You have your partial with your typical twitter modal template html:
<div class="container">
<!-- Modal -->
<div class="modal fade" id="LocationNumberModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
×
</button>
<h4 class="modal-title">
Serial Numbers
</h4>
</div>
<div class="modal-body">
<span id="test"></span>
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
</div>
Then you have your controller method, I use JSON and have a custom class that rendors the view to a string. I do this so I can perform multiple ajax updates on the screen with one ajax call. Reference here: Example but you can use an PartialViewResult/ActionResult on return if you are just doing the one call. I will show it using JSON..
And the JSON Method in Controller:
public JsonResult LocationNumberModal(string partNumber = "")
{
//Business Layer/DAL to get information
return Json(new {
LocationModal = ViewUtility.RenderRazorViewToString(this.ControllerContext, "LocationNumberModal.cshtml", new SomeModelObject())
},
JsonRequestBehavior.AllowGet
);
}
And then, in the view using your modal: You can package the AJAX in your partial and call #{Html.RenderPartial... Or you can have a placeholder with a div:
<div id="LocationNumberModalContainer"></div>
then your ajax:
function LocationNumberModal() {
var partNumber = "1234";
var src = '#Url.Action("LocationNumberModal", "Home", new { area = "Part" })'
+ '?partNumber='' + partNumber;
$.ajax({
type: "GET",
url: src,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
$("#LocationNumberModalContainer").html(data.LocationModal);
$('#LocationNumberModal').modal('show');
}
});
};
Then the button to your modal:
<button type="button" id="GetLocBtn" class="btn btn-default" onclick="LocationNumberModal()">Get</button>
Put the modal and javascript into the partial view. Then call the partial view in your page.
This will handle form submission too.
Partial View
<div id="confirmDialog" class="modal fade" data-backdrop="false">
<div class="modal-dialog" data-backdrop="false">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Missing Service Order</h4>
</div>
<div class="modal-body">
<p>You have not entered a Service Order. Do you want to continue?</p>
</div>
<div class="modal-footer">
<input id="btnSubmit" type="submit" class="btn btn-primary"
value="Submit" href="javascript:"
onClick="document.getElementById('Coordinate').submit()" />
<button type="button" class="btn btn-default" data-
dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
Javascript
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#Coordinate").on('submit',
function (e) {
if ($("#ServiceOrder").val() == '') {
e.preventDefault();
$('#confirmDialog').modal('show');
}
});
});
</script>
Then just call your partial inside the form of your page.
Create.cshtml
#using (Html.BeginForm("Edit","Home",FormMethod.Post, new {id ="Coordinate"}))
{
//Form Code
#Html.Partial("ConfirmDialog")
}