How to load a partial view into a container in _Layout.cshtml - asp.net

Hi can someone please tell me how I can load a PartialView into a div container I have prepared located in _Layout.cshtml (that is completely separate from the link itself). I want it loaded into the container on the click of the following action link:
<span>ContactUs</span>
I would like to do this without javascript because I need to create a model in my controller and pass it to the PartialView and I dont think its possible to pass a strongly typed model to a view using javascript.
If I wanted to I could use:
$('.colorboxLink').click(function () {
$('.colorbox_container').load(this.href);
});
but as I mentioned this does not give me the chance to create and pass a strongly typed model to the partial view...its important that I can create and pass a model to the view because Im getting a null reference exception when I try something like foreach(var item in Model.ItemList) in the partial view.
Heres what my controller looks like:
public virtual ActionResult RenderColorbox(string path)
{
return PartialView(path, null);
}
However, currently, clicking the action link simply renders the PartialView in a new blank page rather than inside the container I have set up.
Thank you all for your help.
EDIT: To load the colorbox I used the following as suggest:
$('.colorboxLink').click(function () {
$('.colorbox_container').load(this.href, function () {
var colorboxOptions = {
inline: true,
scrolling: false,
opacity: ".9",
fixed: true,
onLoad: function () {
$('#cboxContent').css({
"background": "white"
});
$('#cboxLoadedContent').css({
"margin-bottom": "28px",
"height": "558px"
});
}
}
$('#contactColorbox').colorbox(colorboxOptions);
});
But still loads without colorbox, but rather as a pop up modal.

but as I mentioned this does not give me the chance to create and pass
a strongly typed model to the partial view.
It gives you such chance. You are sending an AJAX request to the RenderColorbox action on the ContactPartial controller. Inside this action you can prepare and send whatever complex view model you want to the partial:
public ActionResult RenderColorbox(string path)
{
SomeComplexModel model = ...
return PartialView(path, model);
}
Also make sure that you cancel the default action of the link by returning false from the click handler:
$(function() {
$('.colorboxLink').click(function () {
$('.colorbox_container').load(this.href);
return false;
});
});
If you don't do this, when you click on the link, your AJAX call has barely any chance to execute before the browser redirects away to the target page.

Related

ASP.NET MVC5 - RenderPartial() doesn't executed after returning Partial View

I have the following code:
View:
#model IEnumerable<FormBuilder.Model.Formular>
<div id="divAktiveFormulare">
#{ Html.RenderPartial("Formular/TableAllFormulare", Model.Where(model => model.Status == FormularStatus.Aktiv).ToList()); }
</div>
<div id="divArchivierteFormulare">
#{ Html.RenderPartial("Formular/TableAllFormulare", Model.Where(model => model.Status == FormularStatus.Archiviert).ToList()); }
</div>
function btnArchivieren(e) {
$.ajax({
url: 'Url.Action("Archive", "Formular")',
data: { id: e.target.name },
success: function (data) {
$('#divArchivierteFormulare').html(data);
}
});
}
Controller:
public ActionResult Index()
{
List<Formular> aktiveformulare = _formularManager.GetAllFormulare();
return View(aktiveformulare);
}
public ActionResult Archive(int id)
{
Formular formular = _formularManager.GetFormularByID(id);
if (formular != null)
{
formular.Status = FormularStatus.Archiviert;
_formularManager.UpdateFormular(formular);
}
return PartialView("Formular/TableAllFormulare", _formularManager.GetAllFormulare());
}
I have two divs (divAktiveFormulare and divArchivierteFormulare). In each of them a partial view is rendered. The partial views show a table of the model-items (model is an IEnumerable), and each has a filtered model after an enumaration (f.e. Html.RenderPartial("Formular/TableAllFormulare", model => model.Status == FormularStatus.Archiviert).
While loading the index-page for the first time, everything works perfectly. I can set a breakpoint at the RenderPartial()-lines and it will stop there. Both partial views show its tables correctly after the filtered model.
On my page I have a button and by pressing it it will start the Javascript btnArchivieren, which send an ajax to the controller. The action will return a Partial View() with the updated model.
But now my brakepoint at RenderPartial() will not be fired again. Well, the div is updated yeah, but without filtering the model for the partial views (Model.Where(model => model.Status == FormularStatus.Archiviert). Both partial views are showing the table without filtering by enumaration. Like like i said, my brakepoint wasn't even fired.
What am I doing wrong?
Why aren't the RenderPartial()-lines executed after returning the partial view from the controller with an updated model?
When you use :
#{ Html.RenderPartial("Formular/TableAllFormulare", Model.Where(model => model.Status == FormularStatus.Aktiv).ToList()); }
You are telling your application that it has to call your partial view "Formular/TableAllFormulare" with the data you provided.
It's done only while rendering all the page, not by calling it in ajax.
It's the code inside that partial view that will be executed by the ajax call.
Anyway, I would suggest to place your breakpoint in your controller at this line :
Formular formular = _formularManager.GetFormularByID(id);
For it's that line that will be exectued, and probably where the error is hiding.
EDIT :
You'll just have to do that :
return PartialView("Formular/TableAllFormulare", _formularManager.GetAllFormulare().Where(model => model.Status == FormularStatus.Archiviert).ToList());
I hope you understand why it won't work as you expected it at first, so tell me if you don't. I'll try to explain it better.

Rendering partial view dynamically in ASP.Net MVC3 Razor using Ajax call to Action

I'm trying to create a single page form to create a 'work item'. One of the properties is a drop down for 'work item type'.
Depending on the work item type, the user may need to provide additional information in a name-value-pair style attributes grid (property sheet).
I would like to dynamically render the property sheet as soon as a work item type is selected or changed. Once the user provides all information, he would click submit to create the 'work item'.
This is what I have so far:
#using (Ajax.BeginForm("AttributeData", new AjaxOptions() { UpdateTargetId="AttributeDataCell" }))
{
<div style="float:left">
#{
Html.RenderPartial("CreateWorkItemPartialView");
}
</div>
<div id="AttributeDataCell" style="float:right">
#Html.Action("AttributeData", new {id = 1})
</div>
}
The AttributeData action in the controller simply renders the partial view:
public ActionResult AttributeData(int id = 0)
{
var attributes = _workItemDataService.ListWorkItemTypeAttributes(id);
return PartialView("EditWorkItemAttributesPartialView", attributes);
}
Now I would like to hook this up to the drop-down-list's selection event so that the partial view re-renders in the above table cell at every selection change. I would like to pass in the selected value as id.
One way is to force the form to submit itself (and thus re-render).
If that is the right approach, how do we go about it? Esp., how do we make only the property sheet to re-render?
If there is a better way to achieve the above, please indicate.
Thanks
You could subscribe to the .change() event of the dropdown and trigger an AJAX request:
$(function() {
$('#Id_Of_Your_Drop_Down').change(function() {
// This event will be triggered when the dropdown list selection changes
// We start by fetching the form element. Note that if you have
// multiple forms on the page it would be better to provide it
// an unique id in the Ajax.BeginForm helper and then use id selector:
var form = $('form');
// finally we send the AJAX request:
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function(result) {
// The AJAX request succeeded and the result variable
// will contain the partial HTML returned by the action
// we inject it into the div:
$('#AttributeDataCell').html(result);
}
});
});
});

Display jquery dialog on postback in ASP.NET after saving a new record

What I would like to do is have the user add a new record to the database and popup a JQuery dialog confirming that the new record was saved. I thought this would be a simple exercise. I have a gridview bound to a LINQDataSource to allow the user to view and edit existing records and a textbox and a button to add new codes.
In the head of the document, I have the following:
$('#dialog').dialog({
autoOpen: false,
width: 400,
buttons: {
"Ok": function () {
$(this).dialog("close");
}
}
});
and futher down in the markup I have:
<div id="dialog" title="New Code Added">
<p>"<asp:Literal runat="server" ID="LiteralNewCode"></asp:Literal>" was successfully added.</p>
</div>
So when the user enters a new description and it passes all the validation, it's added to the database and the gridview is rebound to display the new record.
protected void ButtonSave_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
CCRCode.Add( <long list of paramters> );
GridCode.DataBind();
IsNewCode = true;
NewDescription = <new description saved to database>;
}
}
Now, here's where (I thought) I'd set a boolean property to indicate that a new description had been added as well as the text of the new description. See below:
protected bool IsNewCode
{
get { return ViewState["IsNewCode"] != null ? (bool)ViewState["IsNewCode"] : false; }
set { ViewState["IsNewCode"] = value; }
}
private string NewDescription
{
get { return ViewState["NewDescription"] != null ? ViewState["NewDescription"].ToString() : string.Empty; }
set { ViewState["NewDescription"] = value; }
}
Here's where I loose my way. My guess is I want to add functionality to include code similar to:
$('#dialog').dialog('open');
I've added a registerscriptblock method in the page_load event but that didn't work. Any ideas? Or am I just going about this entirely wrong?
Thanks.
Not really get what you want to do. But, i use jquery alot with .NET in my projects. here is how i do, probably could give you a hint.
foo.aspx.cs
public String ScriptToRun = "$('#dialog').dialog('open');";
change the value of ScriptToRun in your C# code
foo.aspx
$(document).ready(function() {<%=ScriptToRun %>});
Remember that whatever you done in backend is going to generate HTML, Css& javascript to browser.
Two ways: one, write the javascript in your server-side code. Or, define a JS method to show the dialog (say named showDialog), and call it via:
Page.ClientScript.RegisterStartupScript(... "showDialog();" ..);
RegisterStartupScript puts the method call at the end, ensure your script is above it to work. You can also wrap it with document.ready call too, to ensure JQuery is properly loaded.
I think that the only think that you have miss is the creation of the dialog when the Dom is ready.
$(document).ready(function() {$('#dialog').dialog('open');});
I posted code in a different question for a custom "MessageBox" class I wrote:
ASP.NET Jquery C# MessageBox.Show dialog uh...issue
the code by default uses the javascript alert() function, but you can define your callback so that it calls your custom javascript method to display the messages.

Pass a jQuery NotifyBar requirement to the next view in a RedirectToAction

I'm using the jQuery NotifyBar quite nicely in an Index view to display business rule errors when a user e.g. clicks a delete link for an item than cannot be deleted. However, if the user adds a new item, they are redirected to the Create view. If the new item is successfully created, the Create action redirects back to the Index view.
My quandary is that I need (have been told) to show a success notification in the above scenario. Previously, to request a notification while remaining on the same view, I was using return JavaScript() for an action result, but when I use return RedirectAction() for the action result, I'm left with nowhere to put the return JavaScript().
The way I see this is that I need to:
a) include information in the return RedirectAction() that tells the 'destination' view to show the notification, or
b) invoke the notification in the 'source' view, instead of the return RedirectAction(), and tell it that when it closes/is closed, to perform the redirect to the 'destination' view.
I have no idea where to begin deciding between these two opetions, nor how to even begin researching how to implement either. All advicem and pointers to advice will be most appreciated.
I like option A the best. You could easily include a querystring value with the return url and have a javascript function waiting on the return page that looks for the querystring value... if present, show notification bar.
Submit action on controller:
public ActionResult Submit(ValueModel valueModel) {
//TODO: Save model to repository
//include something in the route values to act as a querystring flag.
//here, I use "success".
return RedirectToAction("Action", "Controller", new { success = 1 });
}
View action on controller:
public ViewResult Index() {
//TODO: do stuff
return View();
}
Index.aspx:
...
<div class='notificationBar'></div>
<script type="text/javascript">
$(document).ready(function() {
if(window.location.search.substring(1).indexOf("success")) {
//set notification bar here
}
});
</script>
...

How do I clear MVC client side validation errors when a cancel button is clicked when a user has invalidated a form?

I have a partial view that is rendered within a main view. The partial view takes advantage of System.ComponentModel.DataAnnotations and Html.EnableClientValidation().
A link is clicked, and div containing the partial view is displayed within a JQuery.Dialog().
I then click the save button without entering any text in my validated input field. This causes the client side validation to fire as expected, and display the '*required' message beside the invalid field.
When the cancel button is clicked, I want to reset the client side MVC validation back to it's default state and remove any messages, ready for when the user opens the dialog again. Is there a recommended way of doing this?
This answer is for MVC3. See comments below for help updating it to MVC 4 and 5
If you just want to clear the validation-messages so that they are not shown to the user you can do it with javascript like so:
function resetValidation() {
//Removes validation from input-fields
$('.input-validation-error').addClass('input-validation-valid');
$('.input-validation-error').removeClass('input-validation-error');
//Removes validation message after input-fields
$('.field-validation-error').addClass('field-validation-valid');
$('.field-validation-error').removeClass('field-validation-error');
//Removes validation summary
$('.validation-summary-errors').addClass('validation-summary-valid');
$('.validation-summary-errors').removeClass('validation-summary-errors');
}
If you need the reset to only work in your popup you can do it like this:
function resetValidation() {
//Removes validation from input-fields
$('#POPUPID .input-validation-error').addClass('input-validation-valid');
$('#POPUPID .input-validation-error').removeClass('input-validation-error');
//Removes validation message after input-fields
$('#POPUPID .field-validation-error').addClass('field-validation-valid');
$('#POPUPID .field-validation-error').removeClass('field-validation-error');
//Removes validation summary
$('#POPUPID .validation-summary-errors').addClass('validation-summary-valid');
$('#POPUPID .validation-summary-errors').removeClass('validation-summary-errors');
}
I hope this is the effect you seek.
If you are using unobtrusive validation that comes with MVC you can simply do:
$.fn.clearErrors = function () {
$(this).each(function() {
$(this).find(".field-validation-error").empty();
$(this).trigger('reset.unobtrusiveValidation');
});
};
------------------------------------------------------------------------
Third Party Edit:
This mostly worked in my case, but I had to remove the $(this).find(".field-validation-error").empty(); line. This appeared to affect the re-showing of the validation messages when resubmitting.
I used the following:
$.fn.clearErrors = function () {
$(this).each(function() {
$(this).trigger('reset.unobtrusiveValidation');
});
};
and then called it like this:
$('#MyFormId input').clearErrors();
function resetValidation() {
$('.field-validation-error').html("");
}
You can simply define a new function in jQuery:
$.fn.resetValidation = function () {
$(this).each(function (i, e) {
$(e).trigger('reset.unobtrusiveValidation');
if ($(e).next().is('span')) {
$(e).next().empty();
}
});
};
and then use it for your input fields:
$('#formId input').resetValidation();
Thank you. I had a similar question for a slightly different scenario. I have a screen where when you click one of the submit buttons it downloads a file. In MVC when you return a file for download, it doesn't switch screens, so any error messages which were already there in the validation summary remain there forever. I certainly don't want the error messages to stay there after the form has been submitted again. But I also don't want to clear the field-level validations which are caught on the client-side when the submit button is clicked. Also, some of my views have more than one form on them.
I added the following code (thanks to you) at the bottom of the Site.Master page so it applies to all of my views.
<!-- This script removes just the summary errors when a submit button is pressed
for any form whose id begins with 'form' -->
<script type="text/javascript">
$('[id^=form]').submit(function resetValidation() {
//Removes validation summary
$('.validation-summary-errors').addClass('validation-summary-valid');
$('.validation-summary-errors').removeClass('validation-summary-errors');
});
</script>
Thanks again.
You can tap into the validation library methods to do this.
There are two objects of interest: FormContext and FieldContext. You can access the FormContext via the form's __MVC_FormValidation property, and one FieldContext per validated property via the FormContext's fields property.
So, to clear the validation errors, you can do something like this to a form:
var fieldContexts = form.__MVC_FormValidation.fields;
for(i = 0; i < fieldContexts.length; i++) {
var fieldContext = fieldContexts[i];
// Clears validation message
fieldContext.clearErrors();
}
// Clears validation summary
form.__MVC_FormValidation.clearErrors();
Then, you can hook that piece of code to whichever event you need.
Sources for this (quite undocumented) insight:
http://bradwilson.typepad.com/presentations/advanced-asp-net-mvc-2.pdf (Mentions FieldContext)
https://stackoverflow.com/a/3868490/525499 (For pointing out this link, which metions how to trigger client-side validation via javascript)
In order to complete clear the validation artifacts including the message, the coloured background of the input field, and the coloured outline around the input field, I needed to use the following code, where this was (in my case) a Bootstrap modal dialog containing an imbedded form.
$(this).each(function () {
$(this).find(".field-validation-error").empty();
$(this).find(".input-validation-error").removeClass("input-validation-error");
$(this).find(".state-error").removeClass("state-error");
$(this).find(".state-success").removeClass("state-success");
$(this).trigger('reset.unobtrusiveValidation');
});
Here you can use simply remove error message
$('.field-validation-valid span').html('')
OR
$('.field-validation-valid span').text('')
I've this issue for "Validation summery" after form ajax submit and done it like this:
$form.find('.validation-summary-errors ul').html('');
and complete code is:
$("#SubmitAjax").on('click', function (evt) {
evt.preventDefault();
var $form = $(this).closest('form');
if ($form.valid()) {
//Do ajax call . . .
//Clear validation summery
$form.find('.validation-summary-errors ul').html('');
}
});

Resources