2016-05-23 7 views
0

私はこの種の問題が既に何度も解決されていることを知っていますが、提供されたソリューションに基づいて鉱山を修正することができません。動的に追加された要素でMVC - jQueryの検証が機能しない

私は単純なライブラリアプリケーションを構築しています。ブックのコピーを追加する機能があります。これは、jQueryを使用してコントローラのアクションを呼び出し、部分的なビューを返し、DOMに動的に追加されます。

追加された最後の動的要素は、作成されたコピーの追加の詳細を含むフォームです。 DropDownList()(動的に追加された)の値が変更されると、ajax呼び出しがトリガーされます。

$('#authorBooksPlaceHolder').on('change', '#AuthorBooksDropDown', function() { 

    var bookId = $(this).val(); 

    $.get('/Books/AddCopy_RenderDetails/' + bookId, function (data) { 

     $('#bookDetailsPlaceHolder').html(data); 
     $('#bookDetailsPlaceHolder').slideDown(); 
    }); 

    $.validator.unobtrusive.parse('#addCopyForm'); 
}); 

呼び出しがAddCopy_RenderDetailsアクションを呼び出しブックidに基づいてDBからエンティティを取得し、人口の特定のフィールドに新しいコピーを作成します。

コントローラアクション:

public PartialViewResult AddCopy_RenderDetails(int id) 
     { 
      var book = db.LibraryBooks.Find(id); 

      var newCopy = new Book() 
      { 
       Author = book.Author, 
       Title = book.Title, 
       Publisher = book.Publisher, 
       CollectionId = book.CollectionId, 
       Collection = book.Collection 
      }; 

      return PartialView("_AddCopy_Details", newCopy); 
     } 

ビューを移入する必要がある残りのフィールドを表示します。私が持っているにもかかわらず$.validator.unobtrusive.parse('#addCopyForm');

@model CityLibrary.Models.Library.Book 

<div class="vertical-separator"></div> 

<hr /> 

@using (Ajax.BeginForm("AddCopy", "Books", new AjaxOptions 
{ 
    UpdateTargetId = "bookDetailsPlaceHolder" 
}, new { @id = "addCopyForm" })) 
{ 
    @Html.AntiForgeryToken() 

    @Html.HiddenFor(model => model.Author) 
    @Html.HiddenFor(model => model.Title) 
    @Html.HiddenFor(model => model.CollectionId) 
    @Html.HiddenFor(model => model.Collection.Name) 
    @Html.HiddenFor(model => model.Publisher) 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Collection.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Collection.Name, new { htmlAttributes = new { @class = "form-control", @disabled = "" } }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.ISBN, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.ISBN, new { htmlAttributes = new { @class = "form-control", } }) 
      @Html.ValidationMessageFor(model => model.ISBN, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Publisher, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Publisher, new { htmlAttributes = new { @class = "form-control", @disabled = "disabled" } }) 
      @Html.ValidationMessageFor(model => model.Publisher, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.YearPrinted, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.YearPrinted, new { htmlAttributes = new { @class = "form-control", @Value = "" } }) 
      @Html.ValidationMessageFor(model => model.YearPrinted, "", new { @class = "text-danger" }) 
     </div> 
    </div> 


    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="Save" class="btn btn-success btn-block" /> 
     </div> 
    </div> 
} 

は、フォームがレンダリングされるとき(クロームのdevのツールでチェック)、検証がまだPOSTアクションが毎回トリガーされているとして、送信ボタンを押すと、サーバー側で起こる呼び出されます。言い換えれば、次のフィールドにTABする際に検証エラーが表示されることはありません。

検証属性は、フォームの入力であります

enter image description here

私はまた、入力されたISBNがデータベースにすでにあるかどうかをチェックするリモート検証を持っています。明らかにこれはクライアント側で動作しますが、私の場合は単純にそうではありません。

ありがとうございました。

EDIT:

まあ、私は、ビューの最後に以下を追加しました:

<script> 
    $.validator.unobtrusive.parse('#addCopyForm'); 
</script> 

そして、それは動作します。関数上でそれをトリガーするのは何もしません。

+0

ただ、リマインダーのこの平和を試してみてください。 – Shashi

+0

ありがとうございました。 '#authorBooksPlaceHolder'は静的divで、最初は' display:none'となります。 – Dandry

答えて

1

Ajaxは非同期で、htmlがDOMに追加される前に$.validator.unobtrusive.parse('#addCopyForm');コード行が呼び出されています。 successコールバック

$.get('/Books/AddCopy_RenderDetails/' + bookId, function (data) { 
    $('#bookDetailsPlaceHolder').html(data); 
    $('#bookDetailsPlaceHolder').slideDown(); 
    $.validator.unobtrusive.parse('#addCopyForm'); 
}); 
+0

、ありがとう、それは問題を解決しました。 '$ .get(...)'の閉じ括弧の後に '$ .validator.unobtrusive.parse( '#addCopyForm');を追加する理由を教えてください。コールの後に配置されているにもかかわらず、以前に呼び出されたのはなぜですか? – Dandry

+1

Ajaxは非同期です。つまり、残りのコードが実行されている間に実行されるので、 '$ .get()'メソッドがコントローラから部分ビューを返す前に、 '$ .validator.unobtrusive.parse() '#addCopyForm'); 'コード行がヒットします(ただし、その時点でHTMLは追加されていません)。 –

+0

ありがとうございます! – Dandry

1

内側に移動することは#authorBooksPlaceHolderがビューにすでに存在し、動的に読み込まないかどうかを確認、コード

$("form").on("submit", function (e) { 
      e.preventDefault(); 
      $.validator.unobtrusive.parse($('#addCopyForm')); // here you need define your form id 
      if ($(this).valid()) // use to validate the form 
        { 
       //do ajax call 
       $.ajax({ 
        type: "Post", 
        url: "/Books/AddCopy_RenderDetails/" + bookId, 
        contentType: "application/json; charset=utf-8",       
        dataType: "json", 
        success: function (data) {       
        } 
       }); 
      } 
     }); 
+0

ありがとうございますが、私は 'Ajax.BeginForm'を使用してこのコードをすべて挿入しなくて済みました。とにかく、これはそれを完了させる別の方法です。 – Dandry

関連する問題