I want to create text area which will be disabled or invisible at starting.
There's a dropdown list, on selection of last option i.e other, it should enable or make the text area visible and take the value and pass to controller on submission.
Use
#Html.TextArea("Name", null, new { disabled="disabled" })
For You:
<div>
#Html.TextArea("Name", null, new { disabled="true" })
#Html.DropDownList("switch", new List<SelectListItem>() {
new SelectListItem(){Text="Enable", Value="Enable"},
new SelectListItem(){Text="Disable", Value="Disable", Selected=true},
})
</div>
<script>
$(function ($) {
var dropDown = $("#switch");
var txtName = $("#Name");
dropDown.change(function () {
if (dropDown.val() === "Disable")
{
txtName.attr("disabled", true);
}
else {
txtName.removeAttr("disabled");
}
})
})(jQuery)
</script>
You should hide the text area, not only disable it. What you can do is add the html :
#Html.TextArea("Text", null, new { #class="hiddenOptionArea", disabled="disabled" })
and apply the class:
hiddenOptionArea {
display:none
}
Also you better use #Html.EditorFor and make yourself a template for your model, so that you can reuse your html wherever you need it - you can find the link here: http://rachelappel.com/razor/partial-views-in-asp-net-mvc-3-w-the-razor-view-engine/
You should try this for creating disabled textArea
#Html.TextAreaFor(m => m.property, new { id = "txtId", disabled = "disabled" })
Related
I have a list of checkboxes that i want to validate on client side with jQuery but failing. I have already added unobtrusive and jquery validation plugin to my project.
The Model code is:
[Required]
public string name { get; set; }
[SkillValidation(ErrorMessage = "Select at least 3 skills")]
public List<CheckBox> skills { get; set; }
and other model is:
public class CheckBox
{
//Value of checkbox
public int Value { get; set; }
//description of checkbox
public string Text { get; set; }
//whether the checkbox is selected or not
public bool IsChecked { get; set; }
}
Explanation - SkillValidation() is the custom attribute which i have created to do server side validation.
The SkillValidation class code is:
public class SkillValidation : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
List<CheckBox> instance = value as List<CheckBox>;
int count = instance == null ? 0 : (from p in instance
where p.IsChecked == true
select p).Count();
if (count >= 3)
return ValidationResult.Success;
else
return new ValidationResult(ErrorMessage);
}
}
Explanation: This code will validate user to check at least 3 checkboxes on the server side. I did not inherited this class from IClientValidatable interface because i know it wont be possible to do validation from the MVC way (unobtrusive manner).
My View code is:
#model demo.MVC.Models.CB
#{
HtmlHelper.ClientValidationEnabled = true;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
}
#using (Html.BeginForm())
{
<table>
<tr>
<td>
#Html.LabelFor(model => model.name)
#Html.EditorFor(model => model.name)
#Html.ValidationMessageFor(model => model.name)
</td>
<td>
#Html.LabelFor(model => model.skills)
#Html.CheckBoxFor(m => m.skills[0].IsChecked, new { id = "csharpSkill" }) C#
#Html.CheckBoxFor(m => m.skills[1].IsChecked, new { id = "aspSkill" }) ASP.NET
#Html.CheckBoxFor(m => m.skills[2].IsChecked, new { id = "jquerySkill" }) jQuery
#Html.CheckBoxFor(m => m.skills[3].IsChecked, new { id = "mvcSkill" }) ASP.NET MVC
#Html.CheckBoxFor(m => m.skills[4].IsChecked, new { id = "razorSkill" }) Razor
#Html.CheckBoxFor(m => m.skills[5].IsChecked, new { id = "htmlSkill" }) HTML
#Html.ValidationMessageFor(model => model.skills)
</td>
</tr>
<tr><td colspan="2"><button id="submitButton" type="submit">Submit</button></td></tr>
</table>
}
#Scripts.Render("~/jQuery")
#Scripts.Render("~/jQueryValidate")
#Scripts.Render("~/Unobtrusive")
Explanation: In the view i have created the text box for name and 6 checkboxes for the skills created with #Html.CheckBoxFor().
Problem: The problem is that If i remove the 6 checkboxes then client side validation works well for the name text box.
If i put 6 checkboxes and press the button then only the server side validation works for name and checkboxe.
I want client side validation to work for the 6 checkboxes too so that user has to select 3 checkboxes at least.
How can i achieve it ?
thanks
You cannot achieve that using MVC's client side validation (by implementing IClientValidatable and using jquery.validation.unobtrusive.js). The reason is that client side validation rules are applied to form controls, and you do not (and cannot) create a form control for your skills property which is a collection, not a simple value type.
You need to write your own scripts to validate the number of checked checkboxes (and if not valid, make use of the placeholder generated by #Html.ValidationMessageFor(model => model.skills)
To mimic jquery's 'lazy' validation, initially handle the .submit() event, and there after, handle the .click() event of the checkboxes.
Modify your 2nd <td> element to add an id attribute for selecting the checkboxes (see also notes below)
<td id="skills">
.... // your checkboxes
and add the following scripts
var validateSkillsOnCheck = false; // for lazy validation
var requiredSkills = 3;
var skills = $('#skills input[type="checkbox"]');
var errorMessage = 'Select at least 3 skills';
var errorElement = $('span[data-valmsg-for="skills"]');
// function to validate the required number of skills
function validateSkills() {
var selectedSkills = skills.filter(':checked').length;
var isValid = selectedSkills > requiredSkills;
if (!isValid) {
errorElement.addClass('field-validation-error').removeClass('field-validation-valid').text(errorMessage);
} else {
errorElement.addClass('field-validation-valid').removeClass('field-validation-error').text('');
}
return (isValid);
}
$('form').submit(function () {
validateSkillsOnCheck = true;
if (!validateSkills()) {
return false; // prevent submit
}
});
$('#skills').on('click', 'input', function () {
if (validateSkillsOnCheck) {
validateSkills();
}
})
A few side notes.
Tables are for tabular data, not layout and using a <table>
element is not appropriate in your case.
Your #Html.LabelFor(model => model.skills) is not appropriate (you
do not have a form control for skills so clicking on it does not
set focus to anything). That should just be a <span>#Html.DisplayNameFor(m =>m.skills)</span> or similar element.
You should however be creating labels for each checkbox. Your model has 3 properties including Text and Value and its not clear what the difference is between them, and in any case, you never include them in the view. I assume your will want to submit at least the Value property so you know which skills have been selected
<label>
#Html.CheckBoxFor(m =>m.skills[i].IsChecked)
<span>#Model.skills[i].Text</span>
</label>
#Html.HiddenFor(m =>m.skills[i].Value)
Script
$(document).ready(function () {
"use strict";
$.validator.unobtrusive.parse($("#form"));
$("#submit").on("click", function () {
var form = $("#form");
form.validate();
if (form.valid()) {
}
return false;
});
});
HTML
<span>Please enter the amount of orders you wish you process:</span>
<br>
#Html.TextBoxFor(m => m.OrderModel.AmountOfOrders, new {id = "AmountOfOrders"})
#Html.ValidationMessageFor(m=> m.OrderModel.AmountOfOrders)
<input type="submit" value ="Submit" id="submit" />
I seem to have a problem with the script. The DataAnnotations for C# are showing up on the View but even if required fields are empty it will still continue to the other page.
if your button is not given
type="button"
, it will default to
type="submit"
Considering that you are using a form, the form will get submitted by the button click as your javascript is executing.
Try this.
$("#submit").on("click", function (event) {
var form = $("#form");
form.validate();
if (form.valid()) {
}
else
{
event.preventDefault();
return false;
}
});
Always use the submit event for forms, not the click event. That way it will work with key-presses:
$("#submit").on("submit", function () {
var form = $("#form");
form.validate();
if (form.valid()) {
// Proceed with submit!
}
else {
// Stop submit!
return false;
}
});
#Html.DropDownListFor(model => model.Status, new List<SelectListItem>
{ new SelectListItem{Text="Active", Value="1",Selected =true},
new SelectListItem{Text="Deactive", Value="0"}})
If i change the value Active to De active display the one alert box. How to display the alert box.
You could use the change() handler in Jquery to listen for the event.
$( "#targetId").change(function() {
alert( "Something changed handle it here" );
});
http://api.jquery.com/change/
Razor:-
#Html.DropDownListFor(model => model.Status, new List<SelectListItem>
{ new SelectListItem{Text="Active", Value="1",Selected =true},
new SelectListItem{Text="Deactive", Value="0"}})
Jquery(Change event is called when you change the dropdownlist value whose id is attached in below query) :-
<script>
$(document).ready(function(){
$('select#status').change(function() {
alert("value changed. New value is " + $(this).val());
});
});
});
</script>
Add this code in your master layout or in view in which Dropdown is:
First Way:
Jquery CODE:
<script>
$(document).ready(function(){
$('select#status').change(function() {
alert($(this).val());
});
});
</script>
Second Way:
Or you can add your own id like this:
#Html.DropDownListFor(model => model.Status, new List<SelectListItem>
{ new SelectListItem{Text="Active", Value="1",Selected =true},
new SelectListItem{Text="Deactive", Value="0"}
},
null,
new {#id="DDLStatus"})
and script:
<script>
$(document).ready(function(){
$('select#DDLStatus').change(function() {
alert($(this).val());
});
});
</script>
Note: make sure that jquery script file is included in your master layout mostly it is in View --> Shared --> _Layout.cshtml
I have a simple MVC 5 page with a single dropdown list. Based upon the selection made from this dropdown list I enable visibility for one of three divs on the page. The problem I am running into is each div takes space on the page, even if it is not visible. So when I select something from dropdown list that causes the second div to be visible I will see that content shifted down on the page.
Here is the code from the Controller to create the data for the dropdown list.
public ActionResult Index()
{
var searchBy = new List<SearchBy>
{
new SearchBy { Name = "Email Address", Value = "EmailAddress" },
new SearchBy { Name = "Last name, First name", Value = "Name" },
new SearchBy { Name = "Username", Value = "Username" }
};
ViewBag.SearchByOptions = new SelectList(searchBy, "Value", "Name");
return View();
}
Here is my markup for the Index.cshtml
#{
<script type="text/javascript">
$(document).ready(function() {
// Make all three <div>s hidden when the page loads...
document.getElementById("searchByEmail").style.visibility = "hidden";
document.getElementById("searchByName").style.visibility = "hidden";
document.getElementById("searchByUsername").style.visibility = "hidden";
});
function searchBy(selectedItem) {
if (selectedItem == "EmailAddress") {
// Make visible
document.getElementById("searchByEmail").style.visibility = "visible";
// Make in-visible
document.getElementById("searchByName").style.visibility = "hidden";
document.getElementById("searchByUsername").style.visibility = "hidden";
}
if (selectedItem == "Name") {
// Make visible
document.getElementById("searchByName").style.visibility = "visible";
// Make in-visible
document.getElementById("searchByEmail").style.visibility = "hidden";
document.getElementById("searchByUsername").style.visibility = "hidden";
}
if (selectedItem == "Username") {
// Make visible
document.getElementById("searchByUsername").style.visibility = "visible";
// Make in-visible
document.getElementById("searchByEmail").style.visibility = "hidden";
document.getElementById("searchByName").style.visibility = "hidden";
}
};
</script>
}
<h2>Index</h2>
<div>
Search for existing users by: #Html.DropDownList("SelectedItem", (SelectList)ViewBag.SearchByOptions, "-- Select One --", new { onchange = "searchBy($('#SelectedItem').val());" })
</div>
<div id="searchByEmail">
Emails...
</div>
<div id="searchByName">
Names...
</div>
<div id="searchByUsername">
Usernames...
</div>
}
I am not sure what trick is needed to get all of the divs to take the same "real estate" on the page as I will only be showing one of them at a time.
Assuming that you use jQuery, try:
#{
<script type="text/javascript">
$(document).ready(function() {
$("#searchByEmail").hide();
$("#searchByName").hide();
$("#searchByUsername").hide();
});
function searchBy(selectedItem) {
if (selectedItem == "EmailAddress") {
$("#searchByEmail").show();
$("#searchByName").hide();
$("#searchByUsername").hide();
}
if (selectedItem == "Name") {
$("#searchByName").show();
$("#searchByEmail").hide();
$("#searchByUsername").hide();
}
if (selectedItem == "Username") {
$("#searchByUsername").show();
$("#searchByEmail").hide();
$("#searchByName").hide();
}
};
</script>
}
<h2>Index</h2>
<div>
Search for existing users by: #Html.DropDownList("SelectedItem", (SelectList)ViewBag.SearchByOptions, "-- Select One --", new { onchange = "searchBy($('#SelectedItem').val());" })
</div>
Also, check what is the difference between CSS rules:
visibility:hidden
and
display:none
The first just hide the element, but preserve the placeholder the same size as it is visible.
The second removes it from the size and dimension calculations.
.style.display = "block"; /* or none to hide it */
Working in C#, Visual Studio 2012, MVC4 EF.
I have a view that, when a condition is met, I want to be a form. How do I do this without having to have one section with the page elements in a form, and another section with the same page elements not in a form?
Here is my code for the condition:
#if (this.Model.ItemRequestStatusId == Portal.BusinessModel.Entities.ItemRequestStatusId.VendorRepReview
&& this.User.IsInRole("Vendor Rep"))
{
using (Html.BeginForm("Edit", "ItemRequest", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<button id="btn-data-integrity-final-review" class="btn btn-warning pull-right" type="submit">Vendor Review Complete</button>
}
}
else
{
#Html.ActionLink("Edit this request", "Edit", new { id = this.Model.Id }, new { #class = "btn btn-default pull-right" })
}
and then below that condition, I have the page elements/fields. But they currently don't fall within the form (only the submit button is within the form). I want to capture the fields in POST.
The only way to achieve that is to use javascript. For example you could subscribe to the submit event of this form and then clone all the fields into the form before submitting:
$('#formId').submit(function() {
var inputFields = $('#someDivContainingYourInputFields').clone();
$(this).append(inputFields);
});
But a better approach would be to simply organize your markup in such a way that the input fields are inside the form. You could achieve that by moving the form definition outside of the condition and wrap the input fields with it. Only the submit button could stay inside the if.