Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check is a specific form field is valid

I've been searching for a while now and haven't found a solution yet.

I'm an ASP.NET and MVC4/Razor2 newbie, so I'm mostly editing the default project.

Anyway, my issue is that I'm using Twitter Bootstrap and I need to add an error CSS class on a div if the under-laying field is not valid.

So far I have this:

    <div class="control-group error">
      @Html.LabelFor(m => m.Password, new { @class = "control-label" })
      <div class="controls">
        @Html.PasswordFor(m => m.Password)
        @Html.ValidationMessageFor(m => m.Password, null, new { @class = "inline-help error" })
      </div>
    </div>

What should I do to make Razor insert the error class in the first div of my snippet when the field is invalid.

UPDATE: I found a way to do it, but it doesn't feel right in comparison to the rest of the code. Is there a better way or is it the way to do it?

<div class="control-group@((!ViewData.ModelState.IsValidField("Password")) ? " error" : "")">
like image 238
willtrnr Avatar asked Jan 14 '13 17:01

willtrnr


2 Answers

Like this:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString AddClassIfPropertyInError<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        string errorClassName)
    {
        var expressionText = ExpressionHelper.GetExpressionText(expression);
        var fullHtmlFieldName = htmlHelper.ViewContext.ViewData
            .TemplateInfo.GetFullHtmlFieldName(expressionText);
        var state = htmlHelper.ViewData.ModelState[fullHtmlFieldName];
        if (state == null)
        {
            return MvcHtmlString.Empty;
        }

        if (state.Errors.Count == 0)
        {
            return MvcHtmlString.Empty;
        }

        return new MvcHtmlString(errorClassName);
    }
}

Then in your view:

<div class="control-group @Html.AddClassIfPropertyInError(x => x.Email, "error")">
    <label class="control-label">Email</label>
    <div class="controls">
        <input type="text" placeholder="Email" name="Email" />
        <span class="help-inline">@Html.ValidationMessageFor(x => x.Email)</span>
    </div>
</div>
like image 150
Andrey Agibalov Avatar answered Oct 19 '22 20:10

Andrey Agibalov


In addition to what Loki said, I came across to a nice and tidy solution to work with ModelState class and retrieve specific information to implement each validation logic i desired:

Assuming you want to check validation for a class in your model, named "InnerClass", and field "Name" :

if (ModelState["InnerClass.Name"].Errors.Count > 0)
{
    foreach (var error in ModelState["InnerClass.Name"].Errors)
    {
        message = error.ErrorMessage;
        isValidFlag = false;
    }
}

Instead of above condition, you can use this also :

ModelState.IsValidField("InnerClass.Name")

ModelState class has great ways to retrieve validation information, so by using mentioned ways you can get more from it with a little workaround.

Hope it helps you!

like image 42
Homa Pour Mohammadi Avatar answered Oct 19 '22 20:10

Homa Pour Mohammadi