2011-06-24 40 views
14

He creado un pequeño ejemplo aquí solo para replicar el problema. Tengo un establecimiento inflexible vista parcial _Name.cshtml:MVC 3 Razor @ Html.ValidationMessageFor no funciona en la carga parcial a través de jquery.load()

@model ValidationInPartial.ViewModels.MyViewModel 

<h2>@ViewBag.Message</h2> 

    <fieldset> 
     <legend>Name</legend> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.MyName) 
     </div> 
     <div class="editor-field"> 
      @Html.EditorFor(model => model.MyName) 
      @Html.ValidationMessageFor(model => model.MyName) 
     </div> 

     <a href="#" id="reload">Reload Name</a> 

     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 

<script type="text/javascript"> 
    $(document).ready(function() { 
     $("#reload").click(function() { 
      $("#divName").load("Home/NameReload"); 
     }); 
    }); 
</script> 

que se carga y se visualiza dentro de la principal Index.cshtml

<div id="divForm"> 
    @using (Html.BeginForm()) { 

     <div id="divName"> 
      @Html.Partial("_Name") 
     </div> 
    } 
</div> 

Se requiere que el MyName campo y validación se implementa a través atributo requerido inicialmente en MyViewModel

namespace ValidationInPartial.ViewModels 
{ 
    public class MyViewModel 
    { 
     [Required(ErrorMessage = "Please enter a Name.")] 
     public string MyName { get; set; } 
    } 
} 

vez que la página se carga la primera vez, si hace clic en el botón Crear dejando el campo vacío del válida mensaje de ación "Por favor ingrese un nombre". muestra al lado del campo y el campo en sí se vuelve rosa, que es el comportamiento esperado. ahora haciendo clic en el enlace "Actualizar Nombre", que hace un llamada AJAX (jquery.load (...)), se volverá a cargar el parcial, aquí está el código del controlador:

public PartialViewResult NameReload() 
{ 
    MyViewModel myViewModel = new MyViewModel(); 
    ViewBag.Message = "Name Reloaded"; 
    return PartialView("_Name", myViewModel); 
} 

Esta vez si hace clic en el Crear botón dejando el campo vacío El mensaje de validación no aparece al lado del campo, aunque el campo se vuelve rosa. Resulta que al volver a cargar el parcial, @ Html.ValidationMessageFor no procesa el mensaje de validación como la primera vez.

Aquí es los archivos de jQuery utilizo

<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script> 

Me pregunto si esto es un error en la forma en que el motor de la maquinilla de afeitar hace que el Html.ValidationMessageFor @ o es que un problema con jQuery? ¿Alguna idea de por qué sucede esto?

También he leído en alguna parte que la llamada ajax pierde todos los scripts para la página, de hecho, tengo que mantener el código javascript dentro del parcial para que puedan ser renderizados y utilizados nuevamente.

Mientras tanto encontré una solución que se va a hacer de forma manual en el parcial de lo que se suponía iba a ser prestados por @ Html.ValidationMessageFor que es:

<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="MyName"></span> 

Sin embargo esta solución significa que si cambiamos el tipo de validación o solo el mensaje de validación dentro del atributo Requerido en el modelo de vista, necesitamos modificar este fragmento de html codificado en la vista.

Respuesta

18

@NickBork tiene una gran respuesta aquí. La clave es que el motor de representación MVC de ASP.NET no genera el script de validación si no cree que hay un formulario. El ejemplo dado lo piratea, lo compra poniendo en una forma y luego se devuelve la selección de una sección interna de HTML desde, esencialmente arrojando el envoltorio externo del formulario.

Hay otro método para que sólo se puede obtener su punto de vista:

ViewContext.FormContext = new FormContext(); 

Con este método, no habrá realmente salida de código de forma, pero el margen de beneficio de validación estará allí.

Gracias, John

+0

Agregué esta línea en la parte superior de la vista parcial y soluciona el problema. Tan simple al final. Un millón de gracias. –

+2

Hay instancias en las que agregar la línea que el Desarrollador ha notado no funcionará, como el uso de AJAX para obtener una vista parcial. La razón por la que esto sucede es porque la llamada AJAX no activa el complemento de validación para "volver a vincular" a los formularios en la página, lo que no debería ocurrir. En estos casos, es necesario llamar $ .validator.unobtrusive.parse ('# myPartialViewForm'); método. En mi caso, estoy usando Fancybox para renderizar un formulario cuando un usuario hace clic en el botón "agregar". Mi vista parcial llama "$ .validator.unobtrusive.parse ('# wizardForm');" para configurar la validación para la vista parcial. –

+0

¡Amigo, eres increíble! – Darren

1

No recuerdo dónde encontré la solución. La razón es porque está cargando un Vista parcial en una vista que ya ha sido analizada por la biblioteca jquery.validator.unobtrusive. Es necesario volver a analizar la biblioteca discreta

function ReparseValidation(){ 
     jQuery.validator.unobtrusive.parse("#yourcontainer"); 
    } 
+1

Temo pero he intentado que ya, pero no funciona para mí. El problema no es volver a validar la página, sino que @ Html.ValidationMessageFor no procesa el mensaje de validación, es decir, la etiqueta en el ejemplo anterior. –

17

marcado Validación (etiquetas span, atributos de campos personalizados, etc) no se prestan a menos que sus campos están contenidos dentro de una forma. El complemento de validación en sí no funciona con elementos fuera de un formulario.

Cuando ASP.NET representa su Vista parcial, los controles no están dentro de un formulario y, por lo tanto, no obtienen los elementos representados.

Cuando carga contenido parcial, deberá analizar el HTML con un selector jQuery.

En mi muestra a continuación, tengo un TBODY en la página principal Vista que contiene filas. Cuando necesito agregar filas adicionales, realizo una llamada a una Vista que tenía una forma, tabla, tbody y colección de filas.

$.ajax({ 
    type: "POST", 
    url: "/controller/action", 
    data: ({Your: 'dataHere'}), 
    dataType: "html", 
    success: 
     function(response){ 
      $('tbody').append($('tbody',$(response)).html()); 

      //The validation plugin can't bind to the same form twice. 
      //We need to remove existing validators 
      $('form').removeData("validator"); 

      //Refresh the validators 
      $.validator.unobtrusive.parse(document); 
     }, 
    error: 
     function(){ 
      alert('An error occured while attempting to add the new content'); 
     } 
}); 

Tenga en cuenta que estoy usando un selector de jQuery para seleccionar las filas que están dentro de la vista/PartialView que se cargan mediante el uso de AJAX:

$('tbody',$(response)).html() 

El resto de la envoltura simplemente anexa las filas de la AJAX Ver/PartialView a los padres que llaman tbody:

$('tbody').append($('tbody',$(response)).html()); 

un par de otras notas, después de que el plug-in de validación se ha ejecutado en un formulario, que no pueden ser llamados de nuevo sin volver a agregarlo (ver jquery.validate.unobtrusive not working with dynamic injected elements)

Para solucionar este problema, lo primero que llamo el siguiente método para eliminar todos los validadores:

$('form').removeData("validator"); 
$("form").removeData("unobtrusiveValidation"); 

entonces actualizar los validadores utilizando la siguiente:

$.validator.unobtrusive.parse(document); 
+0

Gr8 respuesta ... muchas gracias –

Cuestiones relacionadas