I have two forms on a page. I want the first form to use unobtrusive validation, as it's since automatically generated by ASP.NET MVC Framework. There is a second form, however, which I wrote manually, that should not use unobtrusive validation.
Here's some code:
#using (Html.BeginForm("Add", "Contacts", FormMethod.Post, new { id = "AddForm" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Datos Contacto</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ContactDepartmentID)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ContactDepartmentID, (List<SelectListItem>)ViewBag.ContactDepartments)
#Html.ValidationMessageFor(model => model.ContactDepartmentID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Sex)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Sex, (List<SelectListItem>)ViewBag.Sexs)
#Html.ValidationMessageFor(model => model.Sex)
</div>
</fieldset>
<br />
#Html.HiddenFor(model => model.SerializedEmails, new { data_bind = "value: ko.toJSON($root.emails())" })
#Html.HiddenFor(model => model.SerializedPhones, new { data_bind = "value: ko.toJSON($root.phones())" })
}
<form id="phoneForm" >
<fieldset>
<legend>Teléfonos</legend>
<table class="table">
<tbody data-bind="foreach: phones">
<tr>
<th>
Celular?
</th>
<th>
Phone
</th>
<th>
Extension
</th>
<th>
</th>
</tr>
<tr>
<td>
<input type="checkbox" data-bind="checked: isMobile" />
</td>
<td>
<input class="phone" data-bind='value: phone'/>
</td>
<td>
<input type="text" class="extension" data-bind='value: phoneExtension, enable: !isMobile() ' />
</td>
<td>
<a href='#' data-bind='click: $root.removePhone'>Delete</a>
</td>
</tr>
</tbody>
</table>
<a href='#' data-bind='click: $root.addPhone'>Agregar teléfono</a>
</fieldset>
</form>
<p>
<button onclick="Submit();" type="button" class="btn btn-primary" data-bind='enable: phones().length > 0 || emails().length > 0'>
Create</button>
</p>
JS:
function Submit()
{
var valid = $('#AddForm').valid();
var valid2 = $('#phoneForm').valid();
}
jQuery.validator.addClassRules("phone", {
required: true
});
As a side note: When I remove the unobtrusive validation from the page, the second form validates, but the first does not. If I use unobtrusive validation the first form validates, but the second form does not.
I know I can do the whole validation on the client side—and, if that's the only way, I will do it. I was thinking about a way to continue using unobtrusive validation, but allowing it to be conditionally disabled using e.g. custom attributes.
You can disable the unobtrusive validation from within the razor code via this Html Helper property:
HtmlHelper.ClientValidationEnabled = false;
That way you can have unobtrusive validation on and off for different forms according to this setting in their particular view/partial view.
You can mark the elements or find it all the input of the second form and remove the rules, this sample is for remove all rules of some controls in the form, this cause according with the user selected some options, the values required will be others. for this reason i store the rules to restore it later.
///Remove rules
$("input.rO,textarea.rO").each(function () {
try
{
var rule = $(this).rules();
if (rule) {
$(this).data("rule", rule);
$(this).rules("remove");
}
}
catch(err){}
});
///Restore rules
$("input.rO.om" + v + ",textarea.rO.om"+v).each(function () {
try
{
var rule = $(this).data("rule");
if (rule)
$(this).rules("add", rule);
}
catch(err){}
});
Related
I need to make a custom data grid view with multi column filtering and pagination. so i made a view model winch will encapsulate three class
IEnumerable from the data.
Filter class with some properties
Pager to holder page size, current page, total pages etc ..
Filtering working fine but pagination not :(. as i loose the view model when pressing pagination link "It seems that i need to also submit the search form"
Any one can show how i can submit the form when pressing a link.
here is my view
#model TestFilteringAndPagination.ViewModels.CarViewModel
#{
ViewBag.Title = "Home Page";
}
#*Search form*#
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "frm" }))
{
#Html.HiddenFor(m => Model.Pager.CurrentPage)
#Html.HiddenFor(m => Model.Pager.PageSize)
#Html.HiddenFor(m => Model.Pager.EndPage)
#Html.HiddenFor(m => m.Pager.StartPage)
<div class="form-inline">
<div class="form-group">
<label>Car No</label>
#Html.EditorFor(x => x.Filter.CarNumber, new { #class = "form-control" })
</div>
<div class="form-group">
<label>Line name</label>
#Html.EditorFor(x => x.Filter.LineName, new { #class = "form-control" })
</div>
<button type="submit" class="btn btn-default">Search</button>
</div>
<ul class="pagination">
#for (var page = Model.Pager.StartPage; page <= Model.Pager.EndPage; page++)
{
<li class="#(page == Model.Pager.CurrentPage ? "active" : "")">
#page
</li>
}
</ul>
}
#*Data grid*#
<table class="table">
<thead>
<tr>
<th>
Car number
</th>
<th>
Car Line
</th>
</tr>
</thead>
<tbody>
#foreach (var car in Model.Cars)
{
<tr>
<td>
#Html.DisplayFor(x => car.CarNumber)
</td>
<td>
#Html.DisplayFor(x => car.LineName)
</td>
</tr>
}
</tbody>
</table>
You can install the PagedList.MVC NuGet Package, see this post for more info about how to create exactly what you want.
Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application
This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 5 years ago.
I am trying to display and edit a 'Permit Application'.
If it was a piece of paper the top portion would have personal details to fill in.
The bottom portion would be a vertical list of questions with a blank space at the end of each row to write an answer to each question.
So my model is a PermitApplication object which contains with a 'Requestor' object (The applicant) and an array of 'Response' objects which are questions with a string 'Answer' property.
After a lot of thrashing about I am coming to the conclusion maybe what I am trying to does not work under MVC. i.e. Give this sort of model to the view, edit the personal details, fill in the answers to the questions and post the model back.
The view displays OK but when the submit button is pressed the PermitApplication object passed back to the controller only has the personnel details filled in. The returned Responses object is null.
My MVC skills and understanding is limited so my question is 'What is the correct way to tackle this situation? My View (latest attempt) follows:
#model PermitApply.Models.LclPermitApplication
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(model => model.Requestor.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Requestor.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Requestor.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<h2>Permit Questions</h2>
<table class="table">
<tr>
<th>
Question Id
</th>
<th>Question</th>
<th>QuestionTypeId</th>
</tr>
#foreach (var item in Model.Responses)
{
<tr>
<td>
#Html.DisplayFor(p => item.QuestionId)
</td>
<td>
#Html.DisplayFor(p => item.Question)
</td>
<td>
#Html.DisplayFor(p => item.QuestionTypeId)
</td>
<td>
<div class="col-md-10">
#Html.EditorFor(p => item.Answer, new { id = item.QuestionId })
#Html.ValidationMessageFor(p => item.Answer, "", new { #class = "text-danger" })
</div>
</td>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
}
Try updating the foreach loop to below:
#count = 0;
#foreach (var item in Model.Responses)
{
<tr>
<td>
#Html.DisplayFor(p => item.QuestionId)
</td>
<td>
#Html.DisplayFor(p => item.Question)
</td>
<td>
#Html.DisplayFor(p => item.QuestionTypeId)
</td>
<td>
<div class="col-md-10">
#Html.EditorFor(p => item.Answer, new {name="Responses["+count+"].Answer", id = item.QuestionId })
#Html.ValidationMessageFor(p => item.Answer, "", new { #class = "text-danger" })
</div>
</td>
</tr>
count=count+1;
}
Please read MVC model binding to better understand how MVC binds values to send to controllers. Hope this helps.
Based on count number selected from Dropdown list, i have to generate table rows dynamically. For example, if count is 3, then 3 table rows has to be generated (Each table row have 4 table data). Please can anyone help me to implement this scenario?
Here is View code:
<table id="dynamiccount">
<tr>
<td>
<div class="editor-label">
#Html.Label("please select count")
</div>
</td>
<td>
<div class="editor-field">
#Html.DropDownListFor(model => model.count,#ViewBag.dynamic as SelectList,"select")
#Html.ValidationMessageFor(model => model.count)
</div>
</td>
</tr>
</table>
<table id="dynamic">
<tr>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.value1)
</div>
</td>
<td>
<div class="editor-field">
#Html.DropDownListFor(model => model.value1, #ViewBag.Value1 as SelectList, "select")
#Html.ValidationMessageFor(model => model.value1)
</div>
</td>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.value2)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.value2, #ViewBag.Value2 as SelectList, "select")
#Html.ValidationMessageFor(model => model.value2)
</div>
</td>
<td>
<div class="editor-field">
#Html.DropDownListFor(model => model.value3, #ViewBag.Value3 as SelectList, "select")
#Html.ValidationMessageFor(model => model.value3)
</div>
</td>
</tr>
</table>
Now, based on model.count value selected from dropdownlist, i need to generate table rows accordingly.
What you need is a simple FOR:
for (int i = 1; i <= countDropDown; i++)
{
//Add one Row with its data
}
As you didn't provide your code... the answer is super generic.
UPDATE:
Selecting a DropDownList is a client side event. So, you need to pass to the server the value selected, and return the HTML for the "rows" part. To do this, in Javascript you need to bind the onChange event for the DropDownList to get the selected value. Then... you do an AJAX request to the server "asking for the rows" and passing the row number.
ALSO, you could do it all in client side... generating the rows in client side... but in that case I suspect you will be in problems (not impossible, but tricky) at the moment of posting the user input in those rows to the server.
Your HTML:
<table id="dynamiccount">
<tr>
<td>
<div class="editor-label">
#Html.Label("please select count")
</div>
</td>
<td>
<div class="editor-field">
#Html.DropDownListFor(model => model.count,(SelectList)ViewBag.dynamic,"select")
#Html.ValidationMessageFor(model => model.count)
</div>
</td>
</tr>
</table>
<div id="placeholderForTable">
<div>
Using jQuery:
$( "#select" ).change(function() {
var countSelected = $(this).val();
$.ajax({
type: 'GET',
url: 'UrlToAction', //this Action need to return a PartialView
data: "count=" + countSelected ,
success: function(data){
alert('successful');
$('#placeholderForTable').html(data); //the HTML of the view is placed in the Div whose id is "placeHolderForTable"
}
});
});
The Controller Action:
This is left to you to code :)
Disclaimer: all code was written here, no tested.
I have a model with a DateCreated value that is not scaffolded. Coming to GET Edit controller action I see that the model has a correct value that is passed on to the Edit view. Coming back from the view, POST method, the value for DateCreated is DateTime default. It's lost.
Does anyone know why? Controller and View are scaffolded.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Product product)
{
try
{
if (ModelState.IsValid)
{
product.DateEdited = DateTime.Now;
db.Entry(product).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException dex)
{
Console.Write(dex.Message);
ModelState.AddModelError("", reg6.Resources.UnableToSaveChanges);
}
return View(product);
}
#model reg6.Models.Product
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Product</legend>
<table>
<tr>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
</td>
<td>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
<div>
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
</td>
<tr>
<tr>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
</td>
<td>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
<div>
#Html.ValidationMessageFor(model => model.Description)
</div>
</div>
</td>
<tr>
<tr>
<td>
<div class="editor-label">
#Html.LabelFor(model => model.BasePrice)
</div>
</td>
<td>
<div class="editor-field">
#Html.EditorFor(model => model.BasePrice)
<div>
#Html.ValidationMessageFor(model => model.BasePrice)
</div>
</div>
</td>
<tr>
<tr>
<td>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</td>
<td align="right">
<input type="submit" value="Create" id='CreateButton' />
<td>
</tr>
</table>
</fieldset>
}
In your view place a hidden element for the DateCreated
#Html.HiddenFor(m=>m.DateCreated)
All the hidden elements will be posted to the server.
I have a form that has an input section at the top of the page and in the bottom half it displays a list of the objects that were added. I need to be able to Edit and Delete these objects and I'm not sure where to start or how to do it.
This code display the list of objects.
#if (Model.ListOfRecipients != null)
{
for (int i = 0; i < Model.ListOfRecipients.Count; i++)
{
<div class='recipient-wrapper'>
<div class='decision_block'>
<table class='recipient'>
<tr>
<td class='recipient-title'>
#Html.HiddenFor(model=>model.ListOfRecipients[i].RecipientId)
<h3>
#Html.DisplayTextFor(model => model.ListOfRecipients[i].RecipientName)
#Html.HiddenFor(model => model.ListOfRecipients[i].RecipientName)
</h3>
<div class='delivery-type'>
Delivery Type: #Html.DisplayTextFor(model => model.ListOfRecipients[i].DeliveryType)
#Html.HiddenFor(model => model.ListOfRecipients[i].DeliveryType)
</div>
</td>
<td class='na express'>
#Html.CheckBoxFor(model => model.ListOfRecipients[i].ExpressIndicator)
#Html.HiddenFor(model => model.ListOfRecipients[i].ExpressIndicator)
</td>
<td class='quantity'>
<h3>
Qty #Html.DisplayTextFor(model => model.ListOfRecipients[i].Quantity)
#Html.HiddenFor(model => model.ListOfRecipients[i].Quantity)
</h3>
</td>
<td class='action'>
<input class='button edit_recipient' type='button' value='Edit' />
<input class='button delete_recipient' type='button' value='Delete' />
</td>
</tr>
</table>
<input class='button update_recipient' type='button' value='Update' />
<a class='cancel_update' href='#'>Cancel</a>
</div>
</div>
</div>
}
}
You need to write Edit and Delete action methods in your controller and then set your two buttons to call the appropriate method.
The code for the action methods will depend on several factors that may to broad to address here.
Using Razor Syntax -- sorry the others were using wrong markup:(
<input class='button edit_recipient' type='button' value='Edit'
onclick="location.href='#Url.Action("Edit", "Controller", new { id = Model.Id } )'" />
You could create a delete controller and an edit controller and in the above view have a beside each one that has a delete and edit which recieves the objects id and each button goes to it's own view where they can edit or delete