Validation MVC4 avec bootstrap de razor et twitter

j'ai besoin de valider mon entrée dans MVC4 razor. Le problème est, je veux utiliser Twitter bootstrap et puis définir la classe de message d'erreur pour le haut div comme vu ici: http://getbootstrap.com/css/#forms-control-states

Comment changer la classe du parent div ?

2
demandé sur Amirhossein Mehrvarzi 2013-08-19 22:21:54

5 réponses

avez-vous essayé ce script?

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

j'utilise quelque chose de similaire pour obtenir bootstrap et la validation mvc pour jouer nice

3
répondu Slicksim 2013-08-19 18:25:56

la réponse acceptée nécessitait des modifications pour fonctionner avec Bootstrap 3. J'ai utilisé le suivant avec succès avec MVC 4 et 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");
        }
    });
}();
16
répondu Ben Ripley 2014-10-14 13:03:11

modifier validator par défaut:

// 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);
        }
    }
});

créer un nouveau résumé de validation partielle (de sorte que vous avez le contrôle complet sur le balisage):

@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>

Ajouter un style à votre CSS (pour cacher le résumé de validation lors du chargement initial sans avoir à dépendre du script côté client pour le cacher après le fait):

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

et de rendre votre résumé de validation alternative dans votre vue au lieu de @HTML.Validationsommary ():

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

et vous pouvez y aller. Oh, et pour obtenir le bon style pour les checkbox et radio, en fonction de votre configuration le script ci-dessus, l'attraper, mais le plus simple est de simplement modifier votre c'est à dire de type Boolean.cshtml partielle d'être comme suit (où le Html.FormGroupFor est juste une version légèrement mise à jour de https://github.com/erichexter/twitter.bootstrap.mvc/blob/master/src/Bootstrap/BootstrapSupport/ControlGroupExtensions.cs -il suffit de modifier" groupe-contrôle "les références à" formulaire-groupe "et d'ajouter" controlGroupWrapper.AddCssClass ("has-error"); "à la ligne 58'ish):

@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" })
}

Tout ce qui précède est une compilation de diverses solutions que j'ai trouvées à de nombreux endroits différents qui ont fait le bon mélange. La solution de Ben ci-dessus fonctionne, mais elle fait un peu client-side qui provoque un jitter chaque fois qu'une méthode est appelée (i.e. post, page load, validation error). Ce qui précède fait tout cela vous avez besoin sans avoir tout ce DOM looping.

les différentes réponses trouvées à Bootstrap 3 avec jQuery Validation Plugin couvrent une grande partie de ce qui précède (et le crédit pour une partie importante de ce qui précède va aux diverses affiches là, bien qu'aucune réponse ne couvre tout).

3
répondu Ted 2017-05-23 10:28:48

Solution

Inclure la dernière:

$.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");        
    }
}

actuellement à jquery.valider.discret.js le code suivant montre comment MS permet de s'étendre:

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);
    }
}

vous permet essentiellement de modifier/étendre les options suivantes:

  • errorClass
  • errorement
  • errrrplacement
  • invalidHandler
  • succès

il le fait en regardant la variable globale $.validator.unobtrusive.options (qui n'existe pas à moins que vous le fassiez). defaultOptions est défini à $.validator.unobtrusive.options et execInContext est une méthode qui trouve la méthode applicable dans $.validator.unobtrusive.options et l'exécute avec les arguments originaux (de sorte que la méthode MS originale ne se fait pas engluer).

1
répondu Alex 2017-07-19 22:54:30

j'aime ajouter de la classe côté serveur, et pas côté client, donc, ma solution n'a pas de javascript (dans mon cas, c'est un système simple avec seulement 2 ou 3 Champs sur le formulaire).

il s'agit d'utiliser la même structure à partir des États Form -> Validation à partir de la documentation Bootstrap, disponible en http://getbootstrap.com/css/#forms-control-validation

tout d'abord, j'ai créé un Html Helper pour vérifier si le ModelState est valide, et si a une erreur sur le champ, renvoie une chaîne de caractères (Nom de classe). J'aurais pu le faire directement sur la vue, mais j'aime une vue plus propre. Donc, ma classe:

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;
    }
}

Importations:

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

maintenant, à mon avis, j'ai juste besoin d'utiliser la classe, comme:

<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>
0
répondu Roberto Correia 2017-07-26 14:01:40