Setting initial text for validation message - asp.net

I'm currently using ValidationMessageFor to locate and display any errors in my asp.net MVC3 form. To provide this on a client-side level, I'm also using JQuery's unobtrusive validation.
These methods are fantastic but they seem to be lacking one thing - an option to display an initial 'hint' when the user is in a form field, just like on Twitter's sign up form. To clarify, I'd like this to appear in the same place as the validation message.
Can anyone tell me if this functionality is available and if not, how I would go about implementing it?

Just elaborating on my comment above
The way I implemented this was by creating a "HintFor" html extension
public static MvcHtmlString HintFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression)
{
dynamic attribute = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
return MvcHtmlString.Create(attribute.Description);
}
which just displays what you set the description property on the Display attribute for that viewmodel property
[Display(Name = "Application Title", Description = "Description goes in here")]
public string Title { get; set; }
Then in my front end I formatted each form step as shown (the extra classes are because I'm using the uni-form library to format my form)
<div class="question">
#Html.LabelFor(m => m.Title, new { #class = "label" })
<div class="formHint">
#Html.HintFor(m => m.Title)
</div>
<div class="response">
#Html.TextBoxFor(m => m.Title, new { #class = "textInput", autocomplete = "off" })
</div>
<div class="sidetip">
#Html.ValidationMessageFor(m => m.Title, null, new { #class = "invalid" })
</div>
</div>
Then using a little CSS I set the "formhint" class to display none when the error message is shown
.validation-summary-valid, .field-validation-valid
{
display: none;
}
.input-validation-error + .formHint
{
display: none !important;
}
Hope this helps

Related

Instantiating an object inside of view

I am trying to instantiate an object from inside of my view:
In my model I have an entity object called Listing that has a Property object inside of it:
public class Listing
{
...
public Property ListingProperty { get; set; }
...
}
Inside of my view I am referencing the listing model:
#model Realintory.Models.Listing
...
Inside of a form in this view I am trying to set up the properties of the "Property" object like so:
<div class="form-group">
#Html.LabelFor(model => model.ListingProperty.Address, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ListingProperty.Address)
#Html.ValidationMessageFor(model => model.ListingProperty.Address)
</div>
</div>
This throws a null value exception because it hasn't been instantiated. My question is how do I set this up, I know this must be easy but no matter what I try it's not working on the view side.
Things like this fail badly:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
Property toCreate = new Property();
#Model.ListingProperty = toCreate;
...
}
I realize this is probably a newb question but I cant seem to find the answer anywhere so I didn't want to waste anymore time and figured I would ask.
Your controller is supposed to provide a model that represents the data required by the view. If the view needs that property populated in the model then it's the responsibility of the controller to do it. The view should be using the model, not building it.
To add an arbitrary block of code in a Razor view you can do this:
#{
// ...
}
In this case, maybe something like this is appropriate:
#if (Model.ListingProperty == null)
{
Model.ListingProperty = new Property();
}

Asp.net MVC5 with Bootstrap EditorFor size

I have some modifications to bring to a form which use EditorFor (and using MVC5) and I can't find the way of setting the size of the text box ...
I tried the hard way with:
#Html.EditorFor(model => model.Nom, new{#style="width:400px"})
But this did not work..
Is there an easy way?
In MVC up to version 5, EditorFor does not allow you to specify html elements in that way. It can only be used in non-editor contexts, like TextBoxFor, etc...
In MVC 5.1 they added the ability to specify html attributes in Editor templates, and you can now do this:
#Html.EditorFor(model => model, new { htmlAttributes = new { #class = "form-control" }, })
Using MVC 5 - You need to use [DataType(DataType.MultilineText)] attribute on your view model ejm:
using System.ComponentModel.DataAnnotations;
public class Requests
{
[Display(Name = "Id")]
public int RequestId { get; set; }
[DataType(DataType.MultilineText)]
public string Comments { get; set; }
}
It is not a great idea to apply css class to EditorFor template because an EditorTemplate may can have many elements in that. What you can do is to apply your css thing inside your EditorTempalte file. Checkout this answer for more details.
But if you are simply trying to render a textarea, you may simply use the TextAreaFor helper method.
#Html.TextAreaFor(model => model.Nom, new { #class = "myCustomClass" })
and your css
.myCustomClass
{
width:400px;
}
You may use !IMPORTANT if you specifically want to make sure that this css style overrides the eixsting style.
.myCustomClass
{
width:400px !IMPORTANT;
}
the same but in VB
#Html.TextBoxFor(Function(model) model.nit , New With {.class = "form-control"})
If you want to apply it to all your EditorFor, just change the max-width in your Site.css from 280px to any other value.
Example:
textarea {
/*max-width: 280px;*/
max-width: 900px;
}
This worked for me in MVC 5.1

Rendering fields in ASP.NET Razor view with configurable order

I need to allow customers to specify which fields will be drawn in which order, from among a fixed set of fields (address, home phone, SSN, first name, etc. etc.)
What is the best practice for this? I feel like an HTML helper method like "DrawField" is appropriate, but can I use helpers like Html.EditorFor in the body of an HTML helper method? When modelstate has errors and I redisplay the form, will the submitted values and errors be populated?
The "safest" approach seems to be an ugly big loop:
foreach( Field f in FieldList)
{
if(f.Key == FieldKey.FirstName)
{
#Html.LabelFor(model => model.FirstName, StringResource("firstNameLabel"))
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
<br />
}
if(f.Key == FieldKey.LastName)
{
......
}
}
There's gotta be a better way!
Since the list of fields is fixed I would just order it in the controller and just have n regions in the view that will render the fields in the order they arrive in the model. I would structure the model so that it contains a list of the same object, but the content will be different for each one (First name, last name etc) .You can add whatever meta data you need to your model
#Html.LabelFor(model => model.Items[0].Prop, StringResource(model.Items[0].PropName))
#Html.EditorFor(model => model.Items[0].Prop)
......
That way you don't need any conditionals or loops. It's instead n generic regions driven by the data
Although I haven't tried you can try by creating a custom editor / display templates for the Model that takes care of ordering the fields.
To get a basic idea about model templates check this link http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html
UPDATE:
I've tried a simple example. We have a Person model and I want to control the order in which the FirstName and LastName are displayed.
public class Person
{
[Required(ErrorMessage = "The field is required")]
[Display(Name = "First Name:")]
public string FirstName { get; set; }
[Required(ErrorMessage = "The field is required")]
[Display(Name = "Last Name:")]
public string LastName { get; set; }
}
Create a custom editor template Person.cshtml and place it in the Views/Shared folder. So whenever you call the EditorFor method for
Person this template will be used for rendering. For simplicity I'm passing the order in which they have to displayed as an array of fields through ViewBag.
#model RazorAndJson.Models.Person
#{
var fields = ViewBag.FieldsOrder != null
? ViewBag.FieldsOrder
: new[] { "FirstName", "LastName" };
}
#foreach(string field in fields)
{
<p>
#Html.Label(field)
#Html.Editor(field)
#Html.ValidationMessage(field)
</p>
}

How to add css to a single mvc Helper method when validation fails - from within the model

Does anyone have a simple way of adding a css class to a html label when validation fails, preferably from within the model, in the public IEnumerable Validate(ValidationContext context) override, not with jQuery or in the Controller.
I have my validationsummary giving me the error message I just want to put * next to the failed input and make its label text bold and red.
#Html.LabelFor(model => model.Name)
<div class="editor-field">
#Html.EditorFor(model => model.Name)<br/><br />
</div>
If you have not yet found a solution, look at http://weblogs.asp.net/imranbaloch/archive/2010/07/03/asp-net-mvc-labelfor-helper-with-htmlattributes.aspx
It codes an HTML Helper extension to LabelFor that supports html attributes. You could use this code as a template to modify for your needs. One option would be to detect whether a validation error has occured. A few days ago I wrote something similar:
public static string IsInvalidFor<TModel, TValue>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TValue>> expression,
string cssErrorClass)
{
if (ValidationExtensions.ValidationMessageFor(htmlHelper, expression) != null)
return cssErrorClass;
else return "";
}
if you want to do it in .cs file Model in this case just append this
string name = //ur name property//;
oppdesc = "";
oppdesc += "<span class ="error"+ "\">" + name+ "</span>";
and u define class error as bold and red in ur css.

Styling HTML helpers ASP.NET MVC

If I have an HTML helper like so:
Name:<br />
<%=Html.TextBox("txtName",20) %><br />
How do I apply a CSS class to it? Do I have to wrap it in a span? Or do I need to somehow utilize the HtmlAttributes property of the helper?
You can pass it into the TextBox call as a parameter.
Name:<br/>
<%= Html.TextBox("txtName", "20", new { #class = "hello" }) %>
This line will create a text box with the value 20 and assign the class attribute with the value hello. I put the # character in front of the class, because class is a reserved keyword. If you want to add other attributes, just separate the key/value pairs with commas.
This is how to add a class and a style on the same element...
"x" being the model passed to the view with a property of TextBoxID
#Html.TextBoxFor(x => x.TextBoxID, new { #class = "SearchBarSelect", style = "width: 20px; background-color: green;" })
I did some research and came across this article that seems to have a solution to your question.
Ajax Control Toolkit with ASP.NET MVC#
source: jimzimmerman
ARTICLE LINK
http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=330
QUOTE
So basically if you put the class name
TextboxWatermark on any textbox input
with the title you like to show as the
watermark like this:
<input type="text" class"TextboxWatermark" name="username" id="username" title="Must be at least 6 chars" />
or
<%= Html.TextBox("username", new { #class = "TextboxWatermark", #title = "Must be at least 6 chars" }) %>
What is nice about the second option
is that you get the added benefit of
getting the View Engine to fill out
the value of the textbox if there is
an item in ViewData of the
ViewData.Model that has a var named
'username'.
Use the htmlAttributes parameter with an anonymous type, like tihs:
<%=Html.TextBox("txtName","20", new { #class = "test"}) %>
the helper implementation
public static class LabelExtensioncs
{
public static MvcHtmlString Alarm(this HtmlHelper helper, string target, string text)
{
return MvcHtmlString.Create(string.Format("<p class='alert' style='background-color: #b8f89d;border-radius: 5px;width: 100%;'><b>{0}</b><br /><i>{1}</i></p>", target, text));
}
}
the usage in view section
#Html.Alarm("Title", "please unsure your card no is invisible in your authorized information")
the result
Theres no need to use span, because its not dynamic.
Css:
.testClass {
color: #1600d3;
}
View (Index):
#Html.TextBox("expression", "Text to show.", new { #class = "testClass" })
if you need dynamic options you can use for example:
CSS:
.test class{
background: #ffffff;
}
Controller (Index for test):
[HttpGet]
public ActionResult Index()
{
ViewBag.vbColor = "#000000";
return View();
}
View (Index):
<div>
<span>
#Html.TextBox("expression", "Text to show.", new
{ #class = "testClass", #style="color: " +
#ViewBag.vbColor })
</span>
</div>
Hope it helps.
Is it that much more work?

Resources