I'm working on a project which uses ASPNET MVC 3, unobstrusive javascript and Razor
I have a partial view with Ajax.BeginForm containing fields like this:
#Html.TextBoxFor(model => model.FirstName, new { #class = "txt-input", placeholder = "Eg. First Name", maxlength = 50 })
#Html.ValidationMessageFor(model => model.FirstName, "*", new { #class = "form-comments redtxt" })
Then at the end of the form I have this:
#Html.ValidationSummary(false, "Please complete the required fields", new { #class = "form-comments redtxt" })
When I enter no value it correctly shows "*" near the textbox, and "Please complete the required fields" in the validation summary.
The problem is that when I enter a correct value only the "*" disspears and the "Please complete the required fields" remains.
I need to add this in the css in order to not show "*" nor the "Please complete the required fields" when the patial view is loaded for the first time.
.validation-summary-valid
{
display: none;
}
.field-validation-valid
{
display: none;
}
How can I make the validation summary dissapear when valid data is entered?
Thanks in advance! Guillermo.
As far as i understood ur problem, u can use below written code. Its just a hack.
<script>
jQuery(function () {
jQuery('form')
.find('input')
.bind('keyup', function () {
var _summary = jQuery('.form-comments');
if ($(this).valid()) {
_summary.hide();
}
else {
_summary.show();
}
})
});
</script>
As why it's still displaying I don't know.
But a quick fix is to put an if block around your #Html.ValidationSummary and check to see if the model is valid
# if(!ViewContext.ViewData.ModelState.IsValid){
#Html.ValidationSummary(false, "Please complete the required fields", new { #class = "form-comments redtxt" })
}
I usually put my validation summary in a dialog and i just don't display the dialog div if Page.IsValid is true
--Update here is a code snippet that I know works
#{ if(!ViewContext.ViewData.ModelState.IsValid){
<div id="errors" class="DisplayErrors">
#Html.ValidationSummary()
</div>
}}
<script type="text/javascript">
$(function () {
$(".Date").datepicker();
$(".button").button();
$(".DisplayErrors").dialog({ autoOpen: true, title:"Errors" });
});
</script>
Related
Within my view I have a select box. If a certain value is selected I want more form options to appear below using #if.
#model App.ViewModels.JobVM
<div class="row">
<div class="form-group">
#Html.Label("Job Type", new { #class = "control-label" })
#Html.DropDownListFor(model => model.JobId,
new SelectList(App.ViewModels.JobVM.GetJobs(),
"Value", "Text"),
"--Choose Job Type--",
new { #class = "form-control"})
</div>
</div>
...
#if (Model.JobId == 1)
{
.... more form options
}
However when running if the select option that give Job ID 1; the form options don't render.
Is there a reason why the form options do not appear when the Select option changes? Or will I have to use javascript to accomplish this goal?
It's expected behavior as view is rendered on server once before sending data to browser. However, for displaying additional inputs you can use both methods - js or partial views (even with ajax if you need) you have to use only JavaScript to show/hide other elements of form for required cases.
The #if statement and Model.JobId executed server-side, hence Model.JobId value doesn't change when the dropdown selected value has changed because change event occurred in client-side. By handling change event with JS, you can use AJAX call to set the value and display additional form options which contained inside partial view:
jQuery AJAX call
$('#JobId').change(function () {
var jobId = $(this).val();
if (jobId == 1) {
$.ajax({
type: 'GET', // or 'POST'
url: '#Url.Action("ActionName", "ControllerName")',
data: { JobId : jobId },
success: function (result) {
$('#formoptions').html(result);
},
// other stuff
});
}
else {
$('#formoptions').empty();
}
});
Controller Action
public ActionResult ActionName(int JobId)
{
// do something
return PartialView("_FormOptions", viewmodel);
}
If the form options are already rendered together inside view, instead of using server-side #if block, simply use a <div> placeholder and toggle its visibility like this:
$('#JobId').change(function () {
var jobId = $(this).val();
if (jobId == 1) {
$('#formoptions').show(); // show form options
} else {
$('#formoptions').hide(); // hide form options
}
});
HTML
<div id="formoptions">
<!-- more form options -->
</div>
How do you make a Razors helper "Dropdownlist" or what arguments would have to pass to make it editable. For example if I want to scroll down it should let me or if I want type Instead it should let aswell.
#Html.DropDownList("CustomerId", null, htmlAttributes: new { #class = "form-control" } )
Also, if you I choose to use twitter-typeahead with EF razors how do use the "Editfor" so that once the user click on the right item, it sends the ID of that item to the database. In-other words, how do use a navigation property with razors "Editfor" helper.
#Html.EditorFor(model => model.CustomerId, null, "customer",new {htmlAttributes = new { #class = "form-control" } })
I will try to help you convert the basic example of the following page to a razor page equivalent.
http://twitter.github.io/typeahead.js/examples/
You must know that this jquery plugin displays just a list of strings and the user will select one of the values and then you will have to find the id using C# code. I will just show you how to implement the twitter typehead using razor pages but you will have to make some extra work in order to get the id.
First of all you will need the html part
<div id="the-basics">
<input class="typeahead" type="text" placeholder="States of USA">
</div>
Next you need to declare your list using C#.
List<string> Values = new List<string> { "Value 1", "Value 2", "Value 3" };
Now you will have the following HTML.
var substringMatcher = function(strs) {
return function findMatches(q, cb) {
var matches, substringRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
$.each(strs, function(i, str) {
if (substrRegex.test(str)) {
matches.push(str);
}
});
cb(matches);
};
};
var states = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Values));
$('#the-basics .typeahead').typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
name: 'states',
source: substringMatcher(states)
});
I hope it helps.
I continue to work on a project that I do not fully understand yet. I encountered the following line of code:
<iframe id="AddDialog" style ="overflow: hidden; width:1150px; height:450px;" class="Dialogframe" scrolling="no" srcwait=#Html.Raw("'" + Url.Action("Index", "FieldChooser") + "'") srctarget=#Html.Raw("\"" + Url.Action("Index", "FieldChooser", new { ColumnFormat = false, resultmodel = Guid.Empty, datatype = "", multiselect=false }) + "\"") src=#Html.Raw("\"" + Url.Action("Loading", "FieldChooser") + "\"")></iframe>
Visual Studio tells me that srcwait and srctarget are not valid HTML5-elements, but it seems to work. The Loading View is shown for a few seconds and then the Index() method is executed (the one called in srctarget).
I am also not able to find anything on the internet about the attributes srctarget and srcwait. So what are the differences between src, srctarget and srcwait? Do they even exist or is that some invention of the person that worked on it before me?
I have a function in the FieldChooserController
[HttpPost]
public ActionResult Index(string id)
{
...
}
I want this to be called when I click on the OK button. I assumed that the srcwait part is meant for that because the call looks like that, but the function is never called.
Please bear with me and tell me if you need to see more code, at this point I have no idea what is important.
buttons: {
OK: function() {
//Save selected Value
$( this ).dialog( "close" );
if (GlobalName !=''){
addwhere(GlobalName,opts.sourceel,GlobalDefVal,GlobalDataType,GlobalValue);
}
$('#AddDialog').attr('src', $('#AddDialog').attr('srcwait'));
},
Cancel: function() {
$( this ).dialog( "close" );
$('#AddDialog').attr('src', $('#AddDialog').attr('srcwait'));
}
}
There most probably is a piece of JavaScript running, which sets the src to srcwait when an operation is performed where the user will be waiting for a wile, for example to show a loading screen.
As for your code, if you have a HttpPost annotated Index() method you wish to call upon a button click, you must create a form and let it post there:
#using (Html.BeginForm("Index", "FieldChooser", FormMethod.Post)
{
<input value="OK" type="submit" />
}
I've overridden the default editor template (Object.ascx) to produce form (body) HTML that follows to Twitter Bootstrap's guidelines (http://twitter.github.io/bootstrap/base-css.html#forms) which is executed via Html.EditorForModel().
#if (ViewData.TemplateInfo.TemplateDepth > 1)
{
#(Model == null ? ViewData.ModelMetadata.NullDisplayText : ViewData.ModelMetadata.SimpleDisplayText)
}
else
{
foreach (var property in ViewData.ModelMetadata.Properties.Where(m => m.ShowForEdit #*&& m.ModelType != typeof (System.Data.EntityState)*# && !m.IsComplexType && !ViewData.TemplateInfo.Visited(m)))
{
if (property.HideSurroundingHtml)
{
#Html.Editor(property.PropertyName)
}
else
{
<div class="control-group #(!ViewData.ModelState.IsValidField(property.PropertyName) ? "error" : ViewData.ModelState.ContainsKey(property.PropertyName) ? "success" : "" )">
#if (!string.IsNullOrEmpty(Html.Label(property.PropertyName).ToHtmlString()))
{
#Html.Label(property.GetDisplayName() + (property.IsRequired ? " *" : ""), new { #class = "control-label" })
}
<div class="controls">
#Html.Editor(property.PropertyName)
#Html.ValidationMessage(property.PropertyName, "*", new { #class = "help-inline" })
</div>
</div>
}
}
}
This works well unless I want to tweak the form (e.g. change the ordering or add fieldsets). I basically want to separate part of the above code into another editor template, which resulted in Property.ascx. This will render a label, input and validation message for a given property, executed via Html.Editor("{PropertyName"}) or Html.EditorFor(m => m.{PropertyName}).
<div class="control-group #(!ViewData.ModelState.IsValidField(ViewData.ModelMetadata.PropertyName) ? "error" : ViewData.ModelState.ContainsKey(ViewData.ModelMetadata.PropertyName) ? "success" : "" )">
#if (!string.IsNullOrEmpty(Html.Label(ViewData.ModelMetadata.PropertyName).ToHtmlString()))
{
#Html.Label(ViewData.ModelMetadata.GetDisplayName() + (ViewData.ModelMetadata.IsRequired ? " *" : ""), new { #class = "control-label" })
}
<div class="controls">
#Html.Editor(ViewData.ModelMetadata.PropertyName)
#Html.ValidationMessage(ViewData.ModelMetadata.PropertyName, "*", new { #class = "help-inline" })
</div>
</div>
The problem with the above editor template is that it doesn't render the correct input for the given type. So a date/time property will just render a normal text box without the type attribute.
Am I going about this the right way? Should I be using a standard HTML helper or a partial view? If so, how do we handle the generic nature?
MVC 5.1 includes a fix for exactly this case, Bootstrap support for editor templates.
You can include additional properties for the markup by supplying an anonmyous object as the second parameter to EditorFor
#Html.EditorFor(model => model, new { htmlAttributes = new { #class = "form-control" }, })
I'm using jquery to validate an asp.net form (content within a master page). The required fields validation all works great, but I have a field that is not required, but if it does have text then it needs to be in the proper format. Jquery validates incorrect text just fine, but when the text is empty it stops the form from submitting (no error message though). Anyone have an idea why this could be happening or what to do about it?
// Add validation rule for email
if ($("input[id$='TextBoxEmail']").length) {
$("input[id$='TextBoxEmail']").rules('add', {
required: false,
email: true,
messages: {
email: 'Please enter a valid email.'
}
});
}
I have just set up a similar test and cannot replicate the issue (see code below):
<script type="text/javascript">
$(document).ready(function () {
$("#test").validate();
if ($("input[id$='txtText']").length) {
$("input[id$='txtText']").rules('add', {
required: false,
email: true,
messages: {
email: 'Please enter a valid email.'
}
});
}
});
</script>
<form id="test">
<input type="text" id="txtText" />
<input type="submit" />
</form>
I am using jQuery 1.5.1 and the latest jquery.validate.min.js
I can only suggest that you make the jQuery selector more specific as id$='TextBoxEmail' means ends with 'TextBoxEmail'. This may be an issue if you have conflicting fields names?
We discovered that the workaround for this is to manually remove the validation based on our criteria.
// Add validation rule for first name (default Person type is Individual so the validation is needed as default)
if ($("input[id$='TextBoxFirstName']").length) {
$("input[id$='TextBoxFirstName']").rules('add', {
required: true,
messages: {
required: 'First Name is required for individuals.'
}
});
}
// Add event for checking if first name validation is needed
$('select[id$=DropDownListPersonType]').change(function () {
if ($('select[id$=DropDownListPersonType] option:selected').text() == 'Individual') {
// Add validation rule
$("input[id$='TextBoxFirstName']").rules('add', {
required: true,
messages: {
email: 'First Name is required for individuals.'
}
});
}
else {
// remove rule
$("input[id$='TextBoxFirstName']").rules("remove");
}
});