Partial view doesn't load inside current view - asp.net-mvc

So I have this partial view:
#model QueryQuestionManager.Models.Domain.Answer
<script src="~/Scripts/DynamicList.js"></script>
<div class="editorRow">
#using (Html.BeginCollectionItem("Answers"))
{
<div>
#Html.LabelFor(x => x.AnswerText)
#Html.EditorFor(x => x.AnswerText)
</div>
delete
}
</div>
I want to load this partial view in my main view when someone clicks the link:
#model QueryQuestionManager.Models.Domain.Question
#{
ViewBag.Title = "Create";
}
<script src="~/Scripts/DynamicList.js"></script>
<br />
#using (Html.BeginForm(new { #class = "form", role = "form" }))
{
<div class="form-group">
<div class="editor-label">
#Html.LabelFor(m => m.QuestionText)
</div>
<div class="form-control">
#Html.TextBoxFor(m => m.QuestionText)
#Html.ValidationMessageFor(m => m.QuestionText)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Category)
</div>
<div class="form-control">
#Html.TextBoxFor(m => m.Category)
#Html.ValidationMessageFor(m => m.Category)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Answers)
</div>
<br />
<div id="editorRows">
#foreach (var item in Model.Answers)
{
#Html.Partial("EditorRow", item);
}
</div>
#Html.ActionLink("Add another...", "BlankEditorRow", "Question", new { id = "addItem" })
<br />
<input type="submit" value="Save" class="btn btn-success" />
</div>
}
<br />
<div>
#Html.ActionLink("Back to List", "Index", "Home")
</div>
This is the action result from the controller
public ActionResult BlankEditorRow()
{
return PartialView("EditorRow", new Answer());
}
And then I have a javascript file for the dynamic adding and deleting partial views.
$('#addItem').click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$('#editorRows').append(html);
}
});
return false;
});
$('a.deleteRow').live('click', function () {
$(this).parents('div.editorRow:first').remove();
return false;
});
But for some reason my partial view doesn't load inside my current view and it opens only the partial view.
Am I forgetting something?

I'm thinking you don't want that action link. I believe your jQuery click handler has the correct approach, but your action link is linking to your new URL (Question/BlankEditorRow) and you don't want that. Rather you just need to fetch this html, and insert it as you do, but WITHOUT navigating the main page to that URL.

Instead of the ActionLink, use an anchor tag and a hidden field.
<a id="addItem" href="#" />
<input type="hidden" id="partialViewAction" value="#Url.Action("BlankEditorRow","ControllerName")"
Now in your ajax call, instead of using the href property of the anchor, use the value of the hidden field.
url: $('#partialViewAction').val()

Related

Change modal form depending on the button clicked

I have a table showing the information of the users, with an edit button for each one.
I want to show a modal form with the details for the user I want to edit, but I don't know how to get the details from the list, and passing them to the modal as a model.
Here is my View:
#model MyApp.Models.User
#{
ViewBag.Title = "Users";
var roles = new List<string> { "Manager", "Admin" };
var userRoles = (List<string>)ViewData["userRoles"];
}
<h2>#ViewBag.Title</h2>
#if (userRoles.Any(u => roles.Contains(u)))
{
using (Html.BeginForm("Update", "Admin", FormMethod.Post, new { id = "update-form", value = "" }))
{
<div class="modal fade" id="user-editor" >
<div class="modal-header">
<a class="close" data-dismiss="modal"><h3>×</h3></a>
<h3 id="modal-title">Edit User</h3>
</div>
<div class="modal-body">
<div class="form-group">
#Html.Label("Name", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.Label("Age", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Age, new { #class = "form-control" })
</div>
</div>
</div>
<div class="modal-footer">
<a class="btn" data-dismiss="modal">Close</a>
<input type="submit" class="btn btn-primary" value="Save Changes" />
</div>
</div>
}
}
<table class="table-bordered table-hover" id="tbusers">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
#if (userRoles.Any(u => roles.Contains(u)))
{
<th>Edit</th>
}
</tr>
</thead>
<tbody>
#foreach (var u in users)
{
<tr id="#u.Id">
<td>#u.Name</td>
<td>#u.Age</td>
#if (userRoles.Any(u => roles.Contains(u)))
{
<td><a type="button" class="btn edit-btn" href="#user-editor" data-toggle="modal">Edit</a></td>
}
</tr>
}
</tbody>
</table>
I've created a testing sample which will help you understand how can you achieve this.
Index.cshtml which will show a list of employees
#model IEnumerable<MvcApplication1.Models.Employee>
#using MvcApplication1.Models;
<h2>Index</h2>
<table>
#foreach (Employee item in Model)
{
<tr>
<td>#Html.ActionLink(#item.EmployeeName, "Name", new { id = item.ID })</td>
<td>
<button type="button" data-id='#item.ID' class="anchorDetail btn btn-info btn-sm" data-toggle="modal"
data-target="#myModal">
Open Large Modal</button></td>
</tr>
}
</table>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Details</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
At the same page, reference the following scripts
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
JQuery AJAX call for getting/setting the data of individual employee from ActionMethod at the same page
<script>
$(document).ready(function () {
var TeamDetailPostBackURL = '/Employee/Details';
$(document).on('click', '.anchorDetail', function () {
var $buttonClicked = $(this);
var id = $buttonClicked.attr('data-id');
var options = { "backdrop": "static", keyboard: true };
$.ajax({
type: "GET",
url: TeamDetailPostBackURL,
contentType: "application/json; charset=utf-8",
data: { "Id": id },
datatype: "json",
success: function (data) {
debugger;
$('.modal-body').html(data);
$('#myModal').modal(options);
$('#myModal').modal('show');
},
error: function () {
alert("Dynamic content load failed.");
}
});
});
$("#closbtn").click(function () {
$('#myModal').modal('hide');
});
});
Now Create a class of Employee(because i'm not using EF)
public class Employee
{
public int ID { get; set; }
public string EmployeeName { get; set; }
}
Create controller named Employee and 2 ActionMethods like these:
public ActionResult Index()
{
return View(emp);//sends a List of employees to Index View
}
public ActionResult Details(int Id)
{
return PartialView("Details",
emp.Where(x=>x.ID==Convert.ToInt32(Id)).FirstOrDefault());
}
I'm returning PartialView because I need to load a page within a page.
Details.cshtml
#model MvcApplication1.Models.Employee
<fieldset>
<legend>Employee</legend>
<div class="display-label">
#Html.DisplayNameFor(model => model.ID)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.ID)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.EmployeeName)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.EmployeeName)
</div>
</fieldset>
<p>#Html.ActionLink("Back to List", "Index")</p>
When you execute and visit the Index page of Employee, you'll see screen like this:
And the Modal Dialog with results will be shown like this:
Note: You need to add reference of jquery and Bootstrap and you can further design/customize it according to your needs
Hope it helps!

Validation multiple checkbox form

in the page I have only three checkbox, the client should choose at least one before clicking on the submit button :
Controller :
[HttpPost]
public ActionResult Client(OrderItems model)
{
if (bValidated){
//Code here
}
else
{
model.itemChoosed = false;
return View("Client", model);
}
View Client :
#model WebApp.Models.OrderItems
#using (Html.BeginForm("Client", "Home", FormMethod.Post, new { #class = "form-group", role = "form" }))
{
#Html.AntiForgeryToken();
<h2>Client</h2>
#Html.Partial("SentMessage")
<div>
<div>
<h3>Item 1</h3>
<label>#Html.CheckBoxFor(model => model.CLInfo.Item1) Item 1</label>
</div>
<div>
<h3>Item 2</h3>
<label>#Html.CheckBoxFor(model => model.CLInfo.Item2) Item 2</label>
</div>
<div>
<h3>Item 3</h3>
<label>#Html.CheckBoxFor(model => model.CLInfo.Item3) Item 3</label>
</div>
</div>
<div class="row">
<input type="submit" name="action:Client" id="btnClient" class="btn btn-primary flat btn-large pull-right" value="Client" />
</div>
}
After I choose to put the condition into a Partail View :
Partial View SentMessage:
#model WebApp.Models.OrderItems
#if (!model.itemChoosed)
{
<div>You must choose at least one item</div>
}
I have the error message :
The view 'Client' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Client.aspx
..
~/Views/Home/Client.cshtml
..
but Home/Client.cshtml existe since it's the view
Thanks

Using Html.Begin form and FormMethod.Get resulting in form posting

Using a Razor cshtml file in an MVC/Orchard application.
Form area reads as:
#using (Html.BeginForm("Action", "Controller", FormMethod.Get, new { area = "Area.area"})) {
Html.AntiForgeryToken();
#Html.LabelFor(model => model.Value)
#Html.EditorFor(model => model.Value)
<div class="actions">
#Html.ActionLink("Do Something", "OtherAction", "Controller", new { area = "Area.area"}, new { #class = "button"})
<button type="submit">Submit</button>
}
This results in the following HTML:
<form action="/Location/URL" method="post">
<!---Editor Fields etc-->
<div class="actions">
<a class="button" href="/Location/OtherURL">OtherAction</a>
<button type="submit">Submit</button>
</div>
</form>
As you can see, this form is assigned the POSTmethod, which as far as I can tell is contrary to the use of FormMethod.Get in the FormMethod argument of Html.BeginForm.
One things I did notice whilst testing out another form (the real form is much, much longer so I inserted a very small one to see if the syntax/behaviour checked out) was the following:
#using (Html.BeginForm("Action", "Controller", FormMethod.Get, new {area = "Area.area"})) {
<button value="submit">Test</button>
}
#using (Html.BeginForm("Action", "Controller", FormMethod.Get, new { area = "Area.area"})) {
Html.AntiForgeryToken();
#Html.LabelFor(model => model.Value)
#Html.EditorFor(model => model.Value)
<div class="actions">
#Html.ActionLink("Do Something", "OtherAction", "Controller", new { area = "Area.area"}, new { #class = "button"})
<button type="submit">Submit</button>
}
This resulted in the following:
<form action="/Location/URL" method="post">
<button value="submit">Test</button>
<form action="/Location/URL" area="Area.area" method="get">
<!---Editor Fields etc-->
<div class="actions">
<a class="button" href="/Location/OtherURL">OtherAction</a>
<button type="submit">Submit</button>
</div>
</form>
</form>
So this appears to have made the first form a POST and the second one a GET but has put the second form inside of the first one.
Can anyone shed any light?

Ajax.BeginForm not working with Html.ValidationSummary

I am trying to use the Ajax.BeginForm to post data to a controller. In the case of specific errors, the form should re-render and display the custom error message that was added to the ModelState. For some reason, the error message is not displaying. I am even trying the following test case which is not working, am I missing something?
Edit.cshtml:
#using (Ajax.BeginForm("Edit", "UserInformation", FormMethod.Post, new AjaxOptions { HttpMethod = "Post", InsertionMode = InsertionMode.Replace, UpdateTargetId = "divFormContainerMain", LoadingElementId = "divPreLoader", OnSuccess = "onSuccess" }))
{
<div id="divPreLoader" style="display:none; text-align: center"><img src="#Url.Content("~/Content/images/preLoader.gif")" alt="" /></div>
<div id="divFormContainerMain">
#Html.Partial("_EditPartialView", Model)
</div>
<div class="buttonContainerBottom">
<span class="buttonContainerInner">
<input type="submit" id="btnSave" name="buttonPress" value="save" class="orangeButton" />
</span>
</div>
}
_EditPartialView.cshtml:
#Html.ValidationSummary(false)
<div id="divFormContainerUserInformation" class="formContainer">
<div class="labelContainer">
#Html.LabelFor(m => m.UserName)
</div>
<div class="elementContainer">
#Html.TextBoxFor(m => m.UserName, new { style = "width: 200px" })
#Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="labelContainer">
#Html.LabelFor(m => m.Name)
</div>
<div class="elementContainer">
#Html.TextBoxFor(m => m.Name, new { style = "width: 200px" })
#Html.ValidationMessageFor(m => m.Name)
</div>
<div class="labelContainer">
#Html.LabelFor(m => m.EmailAddress)
</div>
<div class="elementContainer">
#Html.TextBoxFor(m => m.EmailAddress, new { style = "width: 200px" })
#Html.ValidationMessageFor(m => m.EmailAddress)
</div>
.
.
.
.
.
.
</div>
UserController:
[HttpPost]
public ActionResult Edit(UserModel userModel)
{
ModelState.AddModelError("", "This is a test");
return PartialView("_EditPartialView", userModel);
}
Where are your scripts added? In the _layout.cshtml or in the view itself? How are you loading the view? Is it with an ajax request to show a partial view?
If you are loading the partial view through ajax or as a partial view, maybe it could be that the partial view was not yet loaded in the jquery DOM model tree.
I would try the following. Change
<div id="divFormContainerMain">
#Html.Partial("_EditPartialView", Model)
</div>
to
<div id="divFormContainerMain">
#Html.Partial("_EditPartialView", Model)
<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
</div>
or
<div id="divFormContainerMain">
#Html.Partial("_EditPartialView", Model)
#Scripts.Render("~/bundles/jqueryval") //if you have a bundle for it
</div>
My advice is anyway to load the validate and unobtrusive scripts only when you need them and not in the _layout.cshtml page.
Also don't forget to enable the following appSettings in the web.config
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Make sure that you have included the jquery.unobtrusive-ajax.js script to your view after jquery itself. Otherwise the Ajax.BeginForm helper won't do what you think it does:
<script type="text/javascript" src="#Url.Content("~/scripts/jquery-YOUR-VERSION.js")"></script>
<script type="text/javascript" src="#Url.Content("~/scripts/jquery.unobtrusive-ajax.js")"></script>

Modal Delete Button Not Working asp.net

I am making a page that stores clients. Clients can have domains and contacts and jobs.
Each contact/domain/job has edit/delete functionality.
I am using MVC 4 ASP.NET c#
each time you wish to edit/delete it launches a modal form.
The delete view for contact and domain is exactly the same except for the fields that it displays. The domain delete function does not fire anything when it is in partial view. But it succeeds when it is navigated to in the url as a regular view. the contact delete works fine in the partial view.
#model STClient.Models.Domain
#{
ViewBag.Title = "DeleteDomain";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
#using (Html.BeginForm("DeleteDomain", "Client", FormMethod.Post)) {
<div class="modal-header">
<h2>Are you sure you want to delete?</h2>
</div>
<div class="modal-body">
<fieldset>
<div class="display-label">
<h3>
#Html.HiddenFor(model => model.server.ID)
#Html.HiddenFor(model => model.ID)
#Html.DisplayNameFor(model => model.Name):
#Html.DisplayFor(model => model.Name)
</h3>
</div>
<div class="display-label">
<h5>
#Html.DisplayNameFor(model => model.Registrar):
#Html.DisplayFor(model => model.Registrar)
</h5>
</div>
<div class="display-label">
<h5>
#Html.DisplayNameFor(model => model.PrimaryDNS):
#Html.DisplayFor(model => model.PrimaryDNS)
</h5>
</div>
<div class ="display-label">
<h5>
#Html.DisplayNameFor(model => model.SecondaryDNS):
#Html.DisplayFor(model => model.SecondaryDNS)
</h5>
</div>
</fieldset>
</div>
<div class="modal-footer">
<a class="btn" href="">Cancel</a>
<input class="btn btn-danger" type ="submit" value="Delete" />
</div>
}
this is on the details page where the delete link is for the domain.
<div class="modal fade" id="deleteDomain-modal"></div>
<script type="text/javascript">
$(function () {
$(".deleteDomain").click(function () {
$.ajax({
url: "/Client/DeleteDomain",
type: "GET",
data: {id: $(this).attr('id')},
dataType: "html",
success: function(e)
{
$("#deleteDomain-modal").html(e);
}
});
$("#deleteDomain-modal").modal();
});
});
</script>
And finally in the Client Controller
public ActionResult DeleteDomain(int id)
{
Domain domain = db.Domains.Find(id);
if (domain == null)
{
HttpNotFound();
}
return PartialView(domain);
}
[HttpPost, ActionName("DeleteDomain")]
public ActionResult DeleteDomainConfirmed(int id)
{
Domain domain = db.Domains.Find(id);
Server server = db.Servers.Find(id);
db.Domains.Remove(domain);
db.SaveChanges();
db.Servers.Remove(server);
db.SaveChanges();
LogDeleteDomain(domain, server);
return RedirectToAction("Index");
}
I think I had a similar problem. The reason was that parameter value was send as string and not as integer. I had to cast the value. So in your script code you may try to change the line:
data: {id: $(this).attr('id')},
to:
data: {id: parseInt($(this).attr('id'))},
That solved my problem.

Resources