twitter-bootstrap 使用 razor 和 twitter bootstrap 进行 MVC4 验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18320483/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 18:01:24  来源:igfitidea点击:

MVC4 Validation with razor and twitter bootstrap

twitter-bootstrapasp.net-mvc-4razorunobtrusive-validation

提问by Knerd

I need to validate my input in MVC4 razor. The problem is, I want to use twitter bootstrap and then set the error message class for the top divas seen here: http://getbootstrap.com/css/#forms-control-states

我需要在 MVC4 razor 中验证我的输入。问题是,我想使用 twitter bootstrap,然后设置顶部的错误消息类,div如下所示:http: //getbootstrap.com/css/#forms-control-states

How can I change the parent div's class?

我怎样才能改变父母div的班级?

采纳答案by Slicksim

Have you tried this script?

你试过这个脚本吗?

http://blog.ijasoneverett.com/2013/05/asp-net-mvc-validation-with-twitters-bootstrap/

http://blog.ijasoneverett.com/2013/05/asp-net-mvc-validation-with-twitters-bootstrap/

I use something similar for getting bootstrap and mvc validation to play nice

我使用类似的东西来让引导程序和 mvc 验证玩得很好

回答by Ben Ripley

The accepted answer needed modifications to work with Bootstrap 3. I have used the followingwith success with MVC 4 and Bootstrap 3.

接受的答案需要修改才能与 Bootstrap 3 一起使用。我在MVC 4 和 Bootstrap 3 中成功使用了以下内容

$(function () {
 // any validation summary items should be encapsulated by a class alert and alert-danger
    $('.validation-summary-errors').each(function () {
        $(this).addClass('alert');
        $(this).addClass('alert-danger');
    });

    // update validation fields on submission of form
    $('form').submit(function () {
        if ($(this).valid()) {
            $(this).find('div.control-group').each(function () {
                if ($(this).find('span.field-validation-error').length == 0) {
                    $(this).removeClass('has-error');
                    $(this).addClass('has-success');
                }
            });
        }
        else {
            $(this).find('div.control-group').each(function () {
                if ($(this).find('span.field-validation-error').length > 0) {
                    $(this).removeClass('has-success');
                    $(this).addClass('has-error');
                }
            });
            $('.validation-summary-errors').each(function () {
                if ($(this).hasClass('alert-danger') == false) {
                    $(this).addClass('alert');
                    $(this).addClass('alert-danger');
                }
            });
        }
    });

    // check each form-group for errors on ready
    $('form').each(function () {
        $(this).find('div.form-group').each(function () {
            if ($(this).find('span.field-validation-error').length > 0) {
                $(this).addClass('has-error');
            }
        });
    });
});

var page = function () {
    //Update the validator
    $.validator.setDefaults({
        highlight: function (element) {
            $(element).closest(".form-group").addClass("has-error");
            $(element).closest(".form-group").removeClass("has-success");
        },
        unhighlight: function (element) {
            $(element).closest(".form-group").removeClass("has-error");
            $(element).closest(".form-group").addClass("has-success");
        }
    });
}();

回答by Ted

Modify validator defaults:

修改验证器默认值:

// Override jquery validate plugin defaults in order to utilize Twitter Bootstrap 3 has-error, has-success, etc. styling.
$.validator.setDefaults({
    highlight: function(element) {
        $(element).closest('.form-group').addClass('has-error').removeClass('has-success');
    },
    unhighlight: function(element) {
        $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
    },
    errorElement: 'span',
    errorClass: 'help-block',
    errorPlacement: function (error, element) {
        if (element.parent('.input-group').length || element.prop('type') === 'checkbox' || element.prop('type') === 'radio') {
            error.insertAfter(element.parent());
        } else {
            error.insertAfter(element);
        }
    }
});

Create a new validation summary partial (so you have complete control over markup):

创建一个新的验证摘要部分(以便您可以完全控制标记):

@model ModelStateDictionary

<div class="@(Html.ViewData.ModelState.IsValid ? "validation-summary-valid" : "validation-summary-errors") panel panel-danger" data-valmsg-summary="true">
    <div class="panel-heading">
        Please, correct the following errors:
    </div>
    <div class="panel-body">
        <ul>
            @foreach (var modelError in Model.SelectMany(keyValuePair => keyValuePair.Value.Errors))
            {
                <li>@modelError.ErrorMessage</li>
            }
        </ul>
    </div>
</div>

Add one style to your CSS (to hide the validation summary on initial load without needing to depend on client-side scripting to hide it after the fact):

向您的 CSS 添加一种样式(在初始加载时隐藏验证摘要,而无需依赖客户端脚本在事后隐藏它):

.validation-summary-valid { 
    display: none; 
}

And render your alternative validation summary in your view instead of @Html.ValidationSummary():

并在您的视图中呈现您的替代验证摘要,而不是 @Html.ValidationSummary():

   @{Html.RenderPartial("_HtmlValidationSummary", ViewData.ModelState);}

And you're good to go. Oh, and to get the nice styling for checkbox and radio, depending on your setup the above script will catch it, but the easiest is to simply modify your i.e. Boolean.cshtml partial to be like the following (where Html.FormGroupFor is just a slightly updated version of https://github.com/erichexter/twitter.bootstrap.mvc/blob/master/src/Bootstrap/BootstrapSupport/ControlGroupExtensions.cs- just change "control-group" references to "form-group" and add " controlGroupWrapper.AddCssClass("has-error");" on line 58'ish):

你很高兴去。哦,为了获得复选框和单选框的漂亮样式,根据您的设置,上面的脚本将捕获它,但最简单的方法是简单地将您的 ie Boolean.cshtml 部分修改为如下所示(其中 Html.FormGroupFor 只是一个https://github.com/erihexter/twitter.bootstrap.mvc/blob/master/src/Bootstrap/BootstrapSupport/ControlGroupExtensions.cs 的略微更新版本- 只需将“控制组”引用更改为“表单组”并添加“ controlGroupWrapper.AddCssClass("has-error");" 在第 58 行):

@using Bctf.Web.HtmlHelpers
@model bool?

@using (Html.FormGroupFor(x => Model))
{
    <label class="checkbox">
        @Html.CheckBox("", Model.HasValue && Model.Value, new { @class = "tickbox-single-line" }) @ViewData.ModelMetadata.DisplayName
    </label>
    @Html.ValidationMessageFor(x => Model, string.Empty, new { @class = "help-block" })
}

All of the above is compilation of various solutions I've found from many different locations that have made the right mix. Ben's solution above works, but it does a fair bit client-side which causes a jitter whenever some method in it is called (i.e. post, page load, validation error). The above does all that you need without having all that DOM looping.

以上所有内容都是我从许多不同地点找到的各种解决方案的汇编,这些解决方案进行了正确的组合。Ben 上面的解决方案有效,但它在客户端做了一个相当不错的工作,每当调用其中的某个方法(即发布、页面加载、验证错误)时都会导致抖动。以上完成了您需要的所有操作,而无需进行所有 DOM 循环。

The various answers found at Bootstrap 3 with jQuery Validation Plugincover much of the above (and credit for a significant chunk of the above goes to the various posters there, although no one answer covers it all).

Bootstrap 3 with jQuery Validation Plugin 上找到的各种答案涵盖了上述大部分内容(上述大部分内容归功于那里的各种海报,尽管没有一个答案涵盖所有内容)。

回答by Alex

Solution

解决方案

Include last:

包括最后:

$.validator.unobtrusive.options = {
    errorPlacement: function (error, element) {        
        $(element).closest(".form-group").addClass("has-error");
    }
    , success: function (label, element) {
        $(element).closest(".form-group").removeClass("has-error");        
    }
}


Currently in jquery.validate.unobtrusive.js the following code shows how MS allows for extending itself:

目前在 jquery.validate.unobtrusive.js 中,以下代码显示了 MS 如何允许扩展自身:

options: {  // options structure passed to jQuery Validate's validate() method
    errorClass: defaultOptions.errorClass || "input-validation-error",
    errorElement: defaultOptions.errorElement || "span",
    errorPlacement: function () {
        onError.apply(form, arguments);
        execInContext("errorPlacement", arguments);
    },
    invalidHandler: function () {
        onErrors.apply(form, arguments);
        execInContext("invalidHandler", arguments);
    },
    messages: {},
    rules: {},
    success: function () {
        onSuccess.apply(form, arguments);
        execInContext("success", arguments);
    }
}

Allows you to basically override/extend the following options:

允许您基本上覆盖/扩展以下选项:

  • errorClass
  • errorElement
  • errrorPlacement
  • invalidHandler
  • success
  • 错误类
  • 错误元素
  • 错误放置
  • 无效处理程序
  • 成功

It does this by looking at the global variable $.validator.unobtrusive.options(which doesn't exist unless you make it). defaultOptionsis set to $.validator.unobtrusive.optionsand execInContextis a method that finds the applicable method in $.validator.unobtrusive.optionsand executes it with the original arguments (so that the original MS method doesn't get clobbered).

它通过查看全局变量$.validator.unobtrusive.options(除非你创建它不存在)来做到这一点。defaultOptions设置为$.validator.unobtrusive.optionsandexecInContext是一种在其中找到适用方法$.validator.unobtrusive.options并使用原始参数执行它的方法(以便原始 MS 方法不会被破坏)。

回答by Roberto Correia

I like to add class on server side, and not client side, so, my solution has no javascript (in my case, it's a simple system with only 2 or 3 fields on the form).

我喜欢在服务器端添加类,而不是客户端,所以,我的解决方案没有 javascript(在我的例子中,它是一个简单的系统,表单上只有 2 或 3 个字段)。

This is to use the same structure from Form -> Validation States from Bootstrap documentation, available in http://getbootstrap.com/css/#forms-control-validation

这是使用来自 Bootstrap 文档的 Form -> Validation States 中的相同结构,可在http://getbootstrap.com/css/#forms-control-validation 中获得

First, I created a Html Helperto check if the ModelState is valid, and if has a error on the field, return a string (class name). I could have done this directly on the view, but I like a cleaner view. So, my class:

首先,我创建了一个Html Helper来检查 ModelState 是否有效,如果字段上有错误,则返回一个字符串(类名)。我可以直接在视图上完成此操作,但我喜欢更清晰的视图。所以,我的班级:

public static class ErrorHelper
{
    private static string GetPropertyName<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
    {
        // Get field name
        // Code from: https://stackoverflow.com/a/2916344/4794469
        MemberExpression body = expression.Body as MemberExpression;
        if (body != null) return body.Member.Name;

        UnaryExpression ubody = expression.Body as UnaryExpression;
        if (ubody != null) body = ubody.Operand as MemberExpression;

        return body?.Member.Name;
    }

    public static MvcHtmlString ReturnOnError<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string @class)
    {
        var propertyName = GetPropertyName(expression);
        if (propertyName == null)
            return MvcHtmlString.Empty;

        if (htmlHelper.ViewData.ModelState.IsValid || !htmlHelper.ViewData.ModelState.ContainsKey(propertyName))
            return MvcHtmlString.Empty;

        return htmlHelper.ViewData.ModelState[propertyName].Errors.Any()
            ? MvcHtmlString.Create(@class)
            : MvcHtmlString.Empty;
    }
}

Imports:

进口:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;

Now, in my View, I just need to use the class, like:

现在,在我的视图中,我只需要使用该类,例如:

<div class="form-group @Html.ReturnOnError(m => m.Name, "has-error")">
    @Html.LabelFor(m => m.Name, new { @class = "control-label" })
    @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
    @Html.ValidationMessageFor(m => m.Name, null, new { @class = "help-block" })
</div>