English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Analisi dei problemi di tooltip di errore con jquery.validate[.unobtrusive] e Bootstrap

Ci sono già articoli simili, vedere qui, penso che sia un po' complesso, recentemente ho anche intenzione di scrivere uno semplice per il progetto, alcuni punti chiave li registro qui. L'effetto finale è il seguente:

Il backend utilizza Asp.net mvc5, i framework frontend sono: jquery.validate, jquery.validate.unobtrusive, requirejs, Bootstrap, tutti nella versione più/precedente. jquery.validate non va spiegato, è un componente di validazione frontend molto popolare; jquery.validate.unobtrusive si basa su jquery.validate, è stato scritto da Microsoft per abbinarsi a Asp.net mvc, NuGet può trovare Microsoft.jQuery.Unobtrusive.Validation per l'installazione, come utilizzarlo continua a leggere.

Prima di tutto, nel backend definiamo la classe dell'entità:

/// <summary>
/// Informazioni del produttore
/// </summary>
public class Manufacturer : OperatedModel
{
  [Chiave]
  [GeneratoDalDatabase(DatabaseGeneratedOption.Identity)]
  public int ID { get; set; }
  /// <summary>
  /// Codice di credito/numero di registrazione
  /// </summary>
  [Richiesto(ErrorMessage = "Il codice di credito/numero di registrazione non può essere vuoto)]
  [MaxLunghezza(30)]
  public string EnterpriseNo { get; set; }
  /// <summary>
  /// Nome dell'azienda
  /// </summary>
  [Richiesto(ErrorMessage = "Il nome dell'azienda non può essere vuoto)]
  public string EnterpriseName { get; set; }
  /// <summary>
  /// 注册地址
  /// </summary>
  [Required(ErrorMessage = "注册地址不能为空")]
  public string RegisteredAddress { get; set; }
  /// <summary>
  /// 法人
  /// </summary>
  [Required(ErrorMessage = "法人不能为空")]
  public string ArtificialPerson { get; set; }
  /// <summary>
  /// 负责人
  /// </summary>
  [Required(ErrorMessage = "负责人不能为空")]
  public string PIC { get; set; }
  [Required(ErrorMessage = "电话号码不能为空")]
  [RegularExpression(RegexLib.Mobile, ErrorMessage = "电话号码格式不正确")]
  public string Mobile { get; set; }
  [EmailAddress]
  public string Email { get; set; }
  /// <summary>
  /// 商铺号
  /// </summary>
  public string ShopNumber { get; set; }
  /// <summary>
  /// 店铺管理员姓名
  /// </summary>
  public string StoreManagerName { get; set; }
  /// <summary>
  /// 店铺管理员联系方式
  /// </summary>
  [RegularExpression(RegexLib.Mobile, ErrorMessage="电话号码格式不正确")]
  public string StoreManagerNumber { get; set; }
  /// <summary>
  /// 主要执照, 三证合一营业执照
  /// </summary>
  public string MainLicence { get; set; }
  /// <summary>
  /// json, 其他执照,如生产许可证
  /// </summary>
  public string OtherLicence { get; set; }
  /// <summary>
  /// 入驻日期
  /// </summary>
  [Required(ErrorMessage = "数据不能为空")]
  public DateTime EnterDate { get; set; }
  /// <summary>
  /// Data di uscita
  /// </summary>
  [Required(ErrorMessage = "La data di scadenza non può essere vuota")]
  public DateTime QuitDate { get; set; }
  /// <summary>
  /// Saldo disponibile del produttore
  /// </summary>
  public decimal Balance { get; set; }
}

Ogni attributo dell'entità ha regole di verifica Attribute, quando l'utente invia un Model al backend Action, la struttura MVC esegue automaticamente la verifica in base a queste regole, quindi lo sviluppo backend è molto felice. Tuttavia, prima di inviare i dati, è necessario effettuare una prima verifica anche dall'anteprima, se si utilizza jquery.validate, allora è necessario scrivere di nuovo le regole simili nel js o nei tag. È possibile riutilizzare il codice esistente del backend? Prendiamo come esempio l'attributo EnterpriseNo e scriviamo in cshtml:

@Html.TextBoxFor(m => m.BasicInfo.EnterpriseNo, new { placeholder = "Obbligatorio", @class = "form-control" })

L'HTML generato alla fine sarà il seguente:

<input class="form-control" data-val="true" data-val-maxlength="Il campo EnterpriseNo deve essere una stringa o un tipo array di lunghezza massima "30"." data-val-maxlength-max="30" data-val-required="Il codice di credito/numero di registrazione non può essere vuoto" id="BasicInfo_EnterpriseNo" name="BasicInfo.EnterpriseNo" placeholder="Obbligatorio" value="" data-original-title="" title="" type="text">

All'interno del tag sono stati automaticamente aggiunti molti attributi che iniziano con data-, dove data-val indica che il controllo deve essere verificato, mentre gli altri attributi che iniziano con data- rappresentano una serie di regole di verifica e messaggi di errore in caso di fallimento. I messaggi di errore possono essere personalizzati; altrimenti, la struttura fornirà una traduzione automatica del tipo "Il campo EnterpriseNo deve essere una stringa o un tipo array di lunghezza massima 30" linguaggio macchina. Certo, questi attributi non vengono riconosciuti da jquery.validate; per farlo, è necessario utilizzare jquery.validate.unobtrusive.

Ora parliamo di come questi js si utilizzano insieme.

La nuova versione di jquery.validate supporta il modulo AMD, quindi può essere caricata direttamente con requirejs, mentre jquery.validate.unobtrusive non può e richiede una configurazione shim, il codice è il seguente:

require.config({
      baseUrl: '/scripts',
      paths: {
        "jquery": 'jquery-2.2.3.min',
        "knockout":'knockout-3.4.0',
        "bootstrap":'../components/bootstrap/3.3.6/js/bootstrap.min','validate':'jquery.validate',
        'validateunobtrusive':'jquery.validate.unobtrusive.min'
      },
      shim : {
        'bootstrap' : {
          deps : [ 'jquery' ],
          exports : 'bootstrap'
        },
        'validateunobtrusive':{
          deps:['validate'],
          exports: 'validateunobtrusive'
        }
      }
    });

Dopo la configurazione, richiedi nella pagina, quindi clicca sul pulsante submit per inviare il modulo. A partire da questo punto, i vari js iniziano a funzionare. Tuttavia, oltre al fatto che il focus si posa sul primo controllo con validazione fallita, sembra non ci siano altri effetti, persino la funzione di default di jquery.validate di visualizzare i messaggi di errore dopo il controllo (funzione errorPlacement) non c'è più, are you kidding me? In realtà, questo succede perché jquery.validate.unobtrusive sovrascrive la configurazione di errorPlacement (vedi la funzione attachValidation nel codice sorgente), il che ci fa risparmiare una procedura. Poiché il markup html del tooltip viene generato dinamicamente da bootstrap, la funzione errorPlacement non è adatta a noi. Riferendoci al link all'inizio dell'articolo, scegliamo di sovrascrivere la funzione showErrors, il codice principale è il seguente (tooltipvalidator.js):

define(['validateunobtrusive'], function () {}}
  function TooltipValidator() {}
  TooltipValidator.prototype = {
    init: function (validatorOptions, tooltipOptions) {
      tooltipOptions = tooltipOptions || {};
      validatorOptions = validatorOptions || {};
      this._tooltipOptions = $.extend({}, {
        placement: 'top'
      }, tooltipOptions, { animation: false });
      this._validatorOptions = $.extend({}, {
        //errorPlacement: function (error, element) {
        //  // do nothing
        //},
        showErrors: function (errorMap, errorList) {
          for (var i = 0; i < this.successList.length; i++) {
            var success = this.successList[i];
            $(this.successList[i]).tooltip('destroy');
            $(this.successList[i]).parents('div.form-group').removeClass('has-error');
          }
          for (var i = 0; i < errorList.length; i++) {
            var errorElement = $(errorList[i].element);
            errorElement.parents('div.form-group').addClass('has-error');
            errorElement.attr('data-original-title', errorList[i].message).tooltip('show');
          }
        },
        submitHandler: function (form) {
          return false;
        }
      }, validatorOptions)
      this._configTooltip();
      this._configValidator();
    },
    _configTooltip: function () {
      $('[data-val="true"]').tooltip(this._tooltipOptions);
    },
    _configValidator: function () {
      $.validator.setDefaults(this._validatorOptions);
      $.validator.unobtrusive.parse(document);
    }
  }
  return new TooltipValidator();
});

Così possiamo eseguire tooltipvalidator.init nel callback di require senza scrivere ulteriori logiche, e anche i colleghi前端 sono soddisfatti e sorridono. C'è anche un altro punto da notare, guardate la riga 49 del codice, è il passo di inizializzazione di jquery.validate.unobtrusive. Originariamente, jquery.validate.unobtrusive ha già $(function () { $jQval.unobtrusive.parse(document); }); ma $.ready viene eseguito dopo che i Dom elementi sono stati caricati (parola a parte: non dopo essere stati resi), quindi viene eseguito prima che tooltipvalidator abbia la possibilità di _configValidator, il che rende i nostri opzioni di configurazione non validi (se si è in un'applicazione single-page con refreshless, si noterà che le opzioni di configurazione sono validi quando si ricarica la pagina locale, perché $.ready viene eseguito solo durante il caricamento iniziale, mentre il callback di require viene eseguito ogni volta che si carica). Ci sono due soluzioni: 1, far dipendere jquery.validate.unobtrusive da tooltipvalidator; 2, rimuovere $jQval.unobtrusive.parse(document); da jquery.validate.unobtrusive. Abbiamo scelto la seconda soluzione.

Grazie per la lettura, speriamo che possa essere utile a tutti, grazie per il supporto al nostro sito!

Dichiarazione: il contenuto di questo articolo è stato raccolto da Internet, di proprietà del rispettivo autore, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, il sito web non detiene i diritti di proprietà, non è stato editato manualmente e non assume alcuna responsabilità legale. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una email a notice#oldtoolbag.com (al momento dell'invio dell'email, sostituisci # con @) per segnalare il problema e fornire prove pertinenti. Una volta verificata la violazione, il sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Guida di Elasticsearch