<fieldset hides when page re-loads - MVC 5 - asp.net-mvc

EDIT:
Here is the exact problem that I have demonstrate, please have a look and as soon as I click the submit button it post back and lost its state and as you can see in the sample code I have three pages I'm posting the form
1) EmployeeForm, 2) EmployerForm, 3) ContractorForm
https://dotnetfiddle.net/wVtwgW
How do I persist the checkbox?
Once I post the page and it reloads the same page if I have my data-model invalid and it display the error message on the screen but the problem is that, it hides the fieldset and the user has to click the checkbox again to show the fieldset.
my question is: how can I still show the fieldset and show the error message in it?
//my scripts that shows the fieldset
<script>
$(document).ready(function() {
$('#Employee').change(function() {
if (this.checked) {
$('#emp').show();
}
});
});
</script>
//it shows the fieldset with checkbox:
<fieldset class="fieldset-auto-width">
<legend>
Select Employee
</legend>
<table width="auto">
<tr>
<th>
Employee
</th>
<td>
#Html.CheckBox("Employee")
</td>
</tr>
</table>
</fieldset>
//my form where I have all the input text and button etc...
<fieldset id="emp" style="display: none" class="fieldset-auto-width">
<legend>
Employee Display
</legend>
#using (Html.BeginForm("EmployeeServer", "EmployeeForm", FormMethod.Post))
{
#Html.ValidationSummary(true)
<div>..... </div>
}
</fieldset>

Instead of using #Html.CheckBox() use #Html.CheckBoxFor()
<td>
#Html.CheckBoxFor(m => m.Employee)
</td>
this will retain the state of the checkbox when you return the model state errors..
in your javascript, just call the $("#Employee") change event after the page loads..
$(document).ready(function() {
$('#Employee').change(function() {
if (this.checked) {
$('#emp').show();
}
});
$('#Employee').trigger("change");
});
Set the Fieldset display value when view is rendered
<fieldset id="emp" style="#(Model.Employee ? "": "display: none")" class="fieldset-auto-width">
<legend>
Employee Display
</legend>
#using (Html.BeginForm("EmployeeServer", "EmployeeForm", FormMethod.Post))
{
#Html.ValidationSummary(true)
<div>..... </div>
}
</fieldset>
this will hide the fieldset if Model.Employee = false or display it if Model.Employee = true.

Just do it with JavaScript. Look for the rendered element from the validation summary helper, and if it exists then you can show your employee form. You can add it to your already executing script like this:
$(document).ready(function() {
$('#Employee').change(function() {
if (this.checked) {
$('#emp').show();
}
});
//check for validation summary elements
if($('.validation-summary-errors').length > 0){
//and show previous entry if present
$('#emp').show();
}
});

Related

How to load a PartialView with a button click in ASP.NET MVC

I have a page that basically has two side-by-side divs. In the left div I will have an HTML table with several rows, and in each of those rows, I was trying to place a button that would Render Partial to the right div.
What I've tried below doesn't seem to be working correctly, when I click on the button, nothing is rendered to the right div and if I put a break in debug on the partial view it returns the view for every single row. How do I render the partial view on a button click and not have the partial view render automatically?
<div class="float-container">
<div class="float-childsmall">
#foreach (var watchList in Model.ViewExecutingTradesUserWatchListFollowShort)
{
<table id="customers">
<caption class="text-center"><h2>#watchList.WatchListName</h2></caption>
<caption class="text-center"><p style="font:10px;">#watchList.WatchListDescription</p></caption>
<tr>
<th>Ticker</th>
</tr>
#foreach (var ticker in Model.ViewUserWatchListTickerModel.Where(y => y.UserWatchListId == watchList.UserWatchListId).ToList())
{
<tr>
<td><a target="_blank" href="https://finviz.com/quote.ashx?t=#ticker.Ticker">#ticker.Ticker </a></td>
<td>
#{
<button data-url='#Html.Action("_Research", null, new ViewDataDictionary { { "ChartTicker", #ticker.Ticker } });'>
#Html.DisplayFor(modelItem => #ticker.Ticker)
</button>
<!--Html.RenderPartial("_Research", null, new ViewDataDictionary { { "ChartTicker", "META" } });-->
}
</td>
</tr>
}
</table>
}
</div>
<div class="float-child">
#{
Html.RenderPartial("_Research", null, new ViewDataDictionary { { "ChartTicker", "META" } });
}
</div>
</div>
Here is the action
public ActionResult _Research()
{
return PartialView("_Research");
}

jquery Ui tooltip from partial view mvc

I'm wondering is it possible to have a partial view display in a tooltip. I'm trying to design a page that has a group of students and when I hover over a student some details appear about them, a list of their subjects and some other details. I know I can put the items in the title, but I can't get all the info I need from there, and my details view has the info I need. Thanks in advance
Here's my current code
IEnumerable<StudentApp.Models.Student>
#foreach (var item in Model)
{ <div class="col-md-2 col-sm-4">
<img title="#item.Name, #item.StudentNo " class="img img-responsive" src="#item.StudentPic" />
</div>
}
#section scripts
{
<script type="text/javascript">
$(document).ready(function () {
$(document).tooltip();
});
</script>
}
Here's my details view
<div class="display-label">
#Html.DisplayNameFor(model => model.Name)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.Name)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.StudentNo)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.StudentNo)
</div>
#foreach (var item in Model.Students)
{
<li>#item.Course</li>
}
You can use the content option to make the tooltip's contents whatever you need them to be. The MVC code could be placed anywhere in your page, so long as you can use jQuery to grab it (eg. in a noscript tag or some such):
$(document).tooltip({
items: ".myTooltipClass",
content: function() {
// .text() will unescape any contained HTML and render it properly;
// use .html() if your content doesn't contain additional HTML
return $("noscript#myMvcContent").text();
}
});
Here's a fiddle demo: http://jsfiddle.net/guke50uw/
As you can use $(this) inside the content function, you can make use of that with HTML data attributes to return different tooltips for the different items; depends on how your page is structured.
I would use the tooltip's open method and set the content of the tooltip object via AJAX there:
$(document).ready(function () {
$(document).tooltip({ open: function(event, ui) {
$(ui.content).load("[url for returning view contents]");
}
});
you may need to use the instance property of the tooltip or maybe via the ui parameter of the open function to retrieve your student number or other identifier to properly query your partial view, but this should help get you going.

Server Side validation not working on MVC partial view

I have a partial view that's added to the main view via ajax call, triggered by the user clicking a button (the user clicks a button, and the partial view is added to the page).
The partial view is strongly typed to a different model than the main page. In my main page, I display the validation errors at the top, and then also have the message displayed below each field. The validation errors for my partial view are displaying at the top of the page, but they are not displaying with the field itself.
Field from partial view:
<td>
#Html.LabelFor(model => model.EmploymentCompany, "* Employer Name")
<input type="text" name="TempEmployments[#idx].EmploymentCompany" class="field panel-field" maxlength="40" style="width: 250px !important;" value="#EmploymentCompany"/>
#Html.ValidationMessage("EmploymentCompany")
</td>
Rendered as:
<td>
<label for="EmploymentCompany">* Employer Name</label>
<input type="text" name="TempEmployments[0].EmploymentCompany" class="field panel-field" maxlength="40" style="width: 250px !important;">
<span class="field-validation-valid" data-valmsg-for="EmploymentCompany" data-valmsg-replace="true"></span>
<td>
In the controller, where validation is called:
[HttpPost]
public ActionResult Create(Applicant application)
{
this.ModelState.AddModelErrors(application.Validate(update: false));
//if valid, other stuff is done. otherwise:
return View(application);
}
In the main view, where validation errors are displayed at the top:
if (!this.ViewData.ModelState.IsValid)
{
<div class="validation-summary-errors" data-valmsg-summary="true">
<ul>
#foreach (ModelState modelState in ViewData.ModelState.Values)
{
foreach (ModelError error in modelState.Errors)
{
<li>#Html.Raw(error.ErrorMessage)</li>
}
}
</ul>
</div>
}
And in the entity where validation errors are added:
foreach (var job in TempEmployments)
{
if (string.IsNullOrWhiteSpace(job.EmploymentCompany))
{
errorDictionary.Add("EmploymentCompany", "Company Name is required");
}
}
And here is what the errors look like at the top of the page:
And the partial view:

MVC: How to insert items in a grid without refreshing the whole page

I have this view where I create a new company that gets added to the database.
The view is in 2 sections, leftside and rightside.
In the rightside I want to input the trades for that company.
A company can have 1 or more trade and this includes 1 primary trade, and 0 to many other trades.
When the user adds in the other trades, each trade will be added to a list underneath. I have NOT put in the code for this yet. For each trade in the list, he can have the option of removing it.
When he has entered all the details, he clicks submit and all the data is saved in the database.
Now I am thinking of putting in a partial view for the other trades, but I am wondering how I can do this, and every time a trade is selected from autocomplete, the data is posted to a controller method and the partial view is return.
But this will clear the data in the leftside section.
So how should I do this?
My view looks like
#model SCD.ViewModels.SubcontractorViewModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Create Subcontractor</legend>
<section class="wrapper">
<section class="leftside">
<table class="formTable">
<tr>
<td class="leftCell">#Html.LabelFor(model => model.Subcontractor.CompanyName)</td>
<td class="rightCell">#Html.TextBoxFor(model => model.Subcontractor.CompanyName, new { #style = "width: 300px;" })</td>
</tr>
<tr>
<td class="leftCell">#Html.LabelFor(model => model.AddressViewModel.Address1)</td>
<td class="rightCell">#Html.TextBoxFor(model => model.AddressViewModel.Address1, new { #style = "width: 300px;" })</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;" class="rightCell"><input type="submit" value="Save"/></td>
</tr>
</table>
<div style="float: left">#Html.ActionLink(" ", "List", null, new { #class = "buttonBackToList" })</div>
</section>
<section class="rightside">
<table class="formTable">
<tr>
<td class="leftCell">#Html.LabelFor(model => model.PrimaryTrade)</td>
<td class="rightCell"><input type="search" name="searchPrimaryTrade" id="searchPrimaryTrade" data-scd-autocomplete="#Url.Action("AutocompletePrimaryTrade", "DataService")" style = "width: 300px;"/>
<input type="button" id="ResetPrimaryTrade" value="Reset"/>
</td>
</tr>
<tr>
<td class="leftCell">#Html.LabelFor(model => model.OtherTrades)</td>
<td class="rightCell"><input type="search" name="searchOtherTrade" id="searchOtherTrade" data-scd-autocomplete="#Url.Action("AutocompleteOtherTrade", "DataService")" style = "width: 300px;"/>
<input type="button" id="ResetOtherTrade" value="Reset"/>
</td>
</tr>
</table>
</section>
</section>
</fieldset>
}
Ajax is your answer, Whenever you do not want to reload the page then using client side ajax to communicate with the server is the only option.
I would use jQuery or to add the rows via ajax which will insert them into your database and return the populated model again and return this as a PartialView(). Your ajax would then onSuccess: replace your tableID with the returned results.
So your jQuery would be something like:
$('.rightside').children('.formTable').replaceWith(theReturnedPartialFromAjaxCall);
If you are adding a dynamic row there are two options:
On adding a row you can call an ajax request which will also add a blank row to the database and then repopulate your model and return the Partial View. This will now have the model binding in place on the new blank row, deleting the blank row or any row can also be done by ajax as the row now has an ID. Make sure however you put the ID as a hidden field in when you loop through each row.
OR (not the preferred way but probably what you will need to do as you have to perform the save)
You can capture the form collection in the save, if there are multiple rows then store this in an array
public ActionResult Save(MyModel model, FormCollection frm) {
String[] name = frm["name"].Split(',');
}
I don't like this way as it is prone to error and the first method will allow you to bind MVC's model validation

Refresh User Control in MVC

I have 3 user controls in an aspx page in my MVC application.
i bind data from DB from one controller.
on the selection of "Filter / Status" i want to bind data (refresh) to "List" user control with out refreshing "Filter & Status" user controls.
below are my user controls in aspx page.
please help me how to refresh part of the page/user control.
i have tried by returning only "ListView" View data. but its searching for the other 2 views & throwing exception.
<td>
<%Html.RenderPartial("Filter", ViewData["FilterView"]); %>
</td>
<td valign="top" width="15%">
<%Html.RenderPartial("Status", this.ViewData["StatusView"]); %>
</td>
<td valign="top" width="85%">
<%Html.RenderPartial("List", this.ViewData["ListingView"]); %>
</td>
do sth like this
html (aspx page):
<div id="ListingView">
<%Html.RenderPartial("List", this.ViewData["ListingView"]); %>
</div>
...
<input type="button" id="refreshListingView" />
javascript to handle it:
$('#refreshListingView').click(function () {
var selectedStatusId = 'get here proper status id';
$.ajax({
url: '/YourController/GetListingView',
type: "GET",
data: { "statusId": selectedStatusId },
success: function (response) {
$('#ListingView').html(response);
}
});
});
YourController:
[HttpGet]
public ActionResult GetListingView(int statusId)
{
ViewData["ListingView"] = your data filtered by statusId or what you want;
return PartialView("List",ViewData["ListingView"]);
}
Instead of ViewData["ListingView"] I would use dedicated model, but it's just an example. It should work.

Resources