2012-02-16 36 views
5

Tôi đã cố gắng hàng tuần để làm theo một vài hướng dẫn về cách tạo biểu mẫu động cho khả năng thêm một "thành phần" khác vào biểu mẫu. Đây là bài viết tôi đã cố gắng làm theo. http://www.joe-stevens.com/2011/07/24/asp-net-mvc-2-client-side-validation-for-dynamic-fields-added-with-ajax/Mẫu động MVC 3 Sử dụng ViewModel

Ngay bây giờ Im chỉ làm việc thêm nhiều công thứcNgười dùng sử dụng liên kết thêm, nhưng tôi sẽ cần phải có cả hai "ingredientsName" và "recipeIngredient" Số tiền có thể được thêm khi liên kết được nhấp. Vấn đề của tôi là khi tôi chạy ứng dụng, biểu mẫu cho công thức nấu ăn có 0 thay vì một hộp văn bản thực tế. Khi tôi nhấp vào thêm thành phần mới, tôi có thể nhận được một hộp văn bản để thêm, nhưng khi tôi nhập vào một số tiền và bấm lưu, dữ liệu mô hình không được truyền cho bộ điều khiển.

Tôi thậm chí không biết ở đâu bắt đầu với việc sửa lỗi này, tôi không chắc mình có nên sử dụng viewmodel hay không nếu Im đi về điều này hoàn toàn sai. Đây là sơ đồ cơ sở dữ liệu của tôi http://i44.tinypic.com/xp1tog.jpg.

Đây là createView của tôi:

@model ViewModels.RecipeViewModel 
@using Helpers; 



<h2>CreateFullRecipe</h2> 

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

    <script type="text/javascript"> 
     $().ready(function() { 
      $("#add-recipeingredient").click(function() { 
       $.ajax({ 
        url: '@Url.Action("GetNewRecipeIngredient")', 
        success: function (data) { 
         $(".new-recipeingredients").append(data); 
         Sys.Mvc.FormContext._Application_Load(); 
        } 
       }); 
      }); 
     }); 
    </script> 

    @using (Html.BeginForm()) 
    { 
      @Html.ValidationSummary(true) 
    <fieldset> 
     <legend>Recipe</legend> 

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


     <fieldset> 
      <legend>RecipeIngredients</legend> 
      <div class="new-recipeingredients"> 

       @Html.EditorFor(model => model.RecipeIngredients) 

      </div> 
      <div style="padding: 10px 0px 10px 0px"> 
       <a id="add-recipeingredient" href="javascript:void(0);">Add another</a> 
      </div> 
     </fieldset> 

     <div> 
      <input type="submit" value="CreateFullRecipe" /> 
     </div> 

    } 
<div> 
    @Html.ActionLink("Back to List", "Index") 
</div> 

editortemplateview của tôi cho recipeingredient:

@model Models.RecipeIngredient 
@using Helpers; 

@using (Html.BeginAjaxContentValidation("form0")) 
    { 
     using (Html.BeginCollectionItem("RecipeIngedients")) 
     { 
    <div style="padding: 5px 0px 5px 0px"> 
     @Html.LabelFor(model => model.Amount) 
     @Html.EditorFor(model => model.Amount) 
     @Html.ValidationMessageFor(model => Model.Amount) 
    </div> 

     } 
    } 

điều khiển liên quan MY phương pháp:

[HttpGet] 
    public ActionResult CreateFullRecipe() 
    { 
     var recipeViewModel = new RecipeViewModel(); 
     return View(recipeViewModel); 
    } 

    // 
    // POST: /Recipe/Create 

    [HttpPost] 
    public ActionResult CreateFullRecipe(RecipeViewModel recipeViewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Recipes.Add(recipeViewModel.Recipe); 
      db.SaveChanges(); 
      int recipeID = recipeViewModel.Recipe.RecipeID; 
      for (int n = 0; n < recipeViewModel.RecipeIngredients.Count(); n++) 
      { 
       db.Ingredients.Add(recipeViewModel.Ingredients[n]); 
       int ingredientID = recipeViewModel.Ingredients[n].IngredientID; 

       recipeViewModel.RecipeIngredients[n].RecipeID = recipeID; 
       recipeViewModel.RecipeIngredients[n].IngredientID = ingredientID; 
       db.RecipeIngredients.Add(recipeViewModel.RecipeIngredients[n]); 

       db.SaveChanges(); 
      } 

      return RedirectToAction("Index"); 
     } 

     return View(recipeViewModel); 
    } 

    public ActionResult GetNewIngredient() 
    { 
     return PartialView("~/Views/Shared/IngredientEditorRow.cshtml", new Ingredient()); 
    } 

    public ActionResult GetNewRecipeIngredient() 
    { 
     return PartialView("~/Views/Shared/_RecipeIngredientEditRow.cshtml", new RecipeIngredient()); 
    } 

My Xem mẫu:

public class RecipeViewModel 
    { 
     public RecipeViewModel() 
     { 
      RecipeIngredients = new List<RecipeIngredient>() { new RecipeIngredient() }; 
      Ingredients = new List<Ingredient>() { new Ingredient() }; 
      Recipe = new Recipe(); 
     } 

     public Recipe Recipe { get; set; } 
     public IList<Ingredient> Ingredients { get; set; } 
     public IList<RecipeIngredient> RecipeIngredients { get; set; } 
    } 
} 

Nếu có bất kỳ thông tin khác cần thiết để giúp vấn đề của tôi ra xin vui lòng cho tôi biết. Điều này thực sự khiến tôi phát điên vì vậy tôi rất mong nhận được sự giúp đỡ nào mà tôi có thể nhận được Cảm ơn bạn!

Tôi cũng muốn đề cập đến phương pháp điều khiển bài đăng createfullrecipe dành cho danh sách được xác định trước và nó hoạt động khi tôi không lo lắng về việc cho người dùng khả năng thêm thành phần khác, thay vào đó tôi chỉ định dạng có 2 thành phần và quan điểm của tôi đã nhận xét ra mã để tạo ra chúng. Tất cả những gì tôi thực sự muốn làm là lấy viewmodel để truyền dữ liệu biểu mẫu tới controller và tôi có thể xử lý dữ liệu giống như phương thức điều khiển createfullrecipe của tôi bây giờ.

@* @for (int n = 0; n < Model.Ingredients.Count(); n++) 
    { 
     <div class="editor-label"> 
      @Html.LabelFor(model => model.Ingredients[n].IngredientName) 
     </div> 
       <div class="editor-field"> 
      @Html.EditorFor(model => model.Ingredients[n].IngredientName) 
      @Html.ValidationMessageFor(model => model.Ingredients[n].IngredientName) 
     </div> 

     <div class="editor-label"> 
      @Html.LabelFor(model => model.RecipeIngredients[n].Amount) 
     </div> 
       <div class="editor-field"> 
      @Html.EditorFor(model => model.RecipeIngredients[n].Amount) 
      @Html.ValidationMessageFor(model => model.RecipeIngredients[n].Amount) 
     </div> 
    }*@ 

Dưới đây là các lớp mô hình của tôi:

public class Recipe 
{ 
    public int RecipeID { get; set; } 
    public string RecipeName { get; set; } 
    public string Description { get; set; } 
    public int? PrepTime { get; set; } 
    public int? CookTime { get; set; } 
    public string ImageURL { get; set; } 

    public virtual IList<RecipeTag> RecipeTags { get; set; } 
    public virtual IList<Rating> Ratings { get; set; } 
    public virtual IList<RecipeStep> RecipeSteps { get; set; } 
    public virtual IList<RecipeIngredient> RecipeIngredients { get; set; } 

} 

public class RecipeIngredient 
{ 
    public int RecipeIngredientID { get; set; } 
    public string IngredientDesc { get; set; } 
    public string Amount { get; set; } 
    public int RecipeID { get; set; } 
    public int? IngredientID { get; set; } 

    public virtual Recipe Recipe { get; set; } 
    public virtual Ingredient Ingredient { get; set; } 
} 

public class Ingredient 
{ 

    public int IngredientID { get; set; } 
    public string IngredientName { get; set; } 

    public virtual ICollection<RecipeIngredient> RecipeIngredients { get; set; } 
} 
+0

Tôi nói về vấn đề này trong bài đăng trên blog này: http://www.jasoncavett.com/2011/03/using-unobtrusive-jquery-validation.html – JasCav

+0

Ngay bây giờ Im không chắc chắn nếu xác thực là vấn đề lớn nhất của tôi. Tôi không thể có được hình thức năng động để gửi dữ liệu đến bộ điều khiển của tôi. Bây giờ các công cụ không ajax ví dụ nếu tôi gõ vào tên công thức, mà tồn tại trong viewmodel được truyền cho bộ điều khiển của tôi. – papayt

Trả lời

13

Có rất nhiều vấn đề với mã của bạn. Tôi thích đi từng bước để minh họa một ví dụ đơn giản mà bạn có thể thích nghi với nhu cầu của mình.

Models:

public class RecipeViewModel 
{ 
    public Recipe Recipe { get; set; } 
    public IList<RecipeIngredient> RecipeIngredients { get; set; } 
} 

public class Recipe 
{ 
    public string RecipeName { get; set; } 
} 

public class RecipeIngredient 
{ 
    public int Amount { get; set; } 

    [Required] 
    public string IngredientDesc { get; set; } 
} 

Bộ điều khiển:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var recipeViewModel = new RecipeViewModel(); 
     return View(recipeViewModel); 
    } 

    [HttpPost] 
    public ActionResult Index(RecipeViewModel recipeViewModel) 
    { 
     if (!ModelState.IsValid) 
     { 
      // there wre validation errors => redisplay the view 
      return View(recipeViewModel); 
     } 

     // TODO: the model is valid => you could pass it to your 
     // service layer for processing 

     return RedirectToAction("Index"); 
    } 

    public ActionResult GetNewRecipeIngredient() 
    { 
     return PartialView("~/Views/Shared/EditorTemplates/RecipeIngredient.cshtml", new RecipeIngredient()); 
    } 
} 

View (~/Views/Home/Index.cshtml):

@model RecipeViewModel 

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> 
<script type="text/javascript"> 
    $(function() { 
     $('#add-recipeingredient').click(function() { 
      $.ajax({ 
       url: '@Url.Action("GetNewRecipeIngredient")', 
       type: 'POST', 
       success: function (data) { 
        $('.new-recipeingredients').append(data); 
       } 
      }); 
      return false; 
     }); 
    }); 
</script> 

@using (Html.BeginForm()) 
{ 
    @Html.ValidationSummary(true) 

    <div> 
     @Html.LabelFor(model => model.Recipe.RecipeName) 
     @Html.EditorFor(model => model.Recipe.RecipeName) 
     @Html.ValidationMessageFor(model => model.Recipe.RecipeName) 
    </div> 

    <fieldset> 
     <legend>RecipeIngredients</legend> 
     <div class="new-recipeingredients"> 
      @Html.EditorFor(model => model.RecipeIngredients) 
     </div> 
     <div style="padding: 10px 0px 10px 0px"> 
      <a id="add-recipeingredient" href="javascript:void(0);">Add another</a> 
     </div> 
    </fieldset> 

    <div> 
     <input type="submit" value="CreateFullRecipe" /> 
    </div> 
} 

biên tập mẫu (~/Views/Shared/EditorTemplates/RecipeIngredient.cshtml):

@model RecipeIngredient 

@using (Html.BeginCollectionItem("RecipeIngredients")) 
{ 
    <div> 
     @Html.LabelFor(model => model.Amount) 
     @Html.EditorFor(model => model.Amount) 
     @Html.ValidationMessageFor(model => model.Amount) 
    </div> 

    <div> 
     @Html.LabelFor(model => model.IngredientDesc) 
     @Html.EditorFor(model => model.IngredientDesc) 
     @Html.ValidationMessageFor(model => model.IngredientDesc) 
    </div> 
} 
+0

Cảm ơn bạn đã giúp đỡ tôi thực sự đánh giá cao nó. Tôi đã cập nhật bài đăng của mình để bao gồm các mô hình đã tồn tại có thể giúp trả lời. Tôi cũng có thể sử dụng một số trợ giúp để xác định nếu tôi chỉ nên kết hợp các bảng bình thường Thành phần và recipeIngredient thành một bảng/mô hình để đơn giản hóa mọi thứ? Tôi cũng cập nhật js và quan điểm của tôi với cách tiếp cận sạch hơn của bạn, nhưng phương pháp điều khiển bài vẫn không có dữ liệu biểu mẫu của tôi trong thông qua trong viewModel. Tôi cho rằng nó có liên quan đến cách thiết lập mô hình của tôi? – papayt

+0

@papayt, bạn đã thử mã của tôi chưa? Như tôi đã nói có rất nhiều vấn đề với bạn. Ví dụ bạn có 'using (Html.BeginCollectionItem (" RecipeIngedients "))' trong khi chính xác là 'using (Html.BeginCollectionItem (" RecipeIngredients "))' đơn giản vì thuộc tính của bạn được gọi là 'RecipeIngredients' và không phải' RecipeIngedients'. Một vấn đề khác là với tên và vị trí của mẫu trình soạn thảo của bạn. Vì vậy, tôi khuyên bạn nên sử dụng mã của tôi làm cơ sở cho tiện ích. –

+0

O wow Tôi thậm chí không bao giờ nhận ra tôi đã có một lỗi đánh máy với (Html.BeginCollectionItem ("RecipeIngedients")), cảm ơn! Tôi đã chuyển mẫu trình chỉnh sửa đã đổi tên của mình sang thư mục bạn đã đề xuất. Và ... Tuyệt vời! Tôi vừa thử nghiệm phần recipeIngredient động của mã của tôi với khả năng thêm một recipeIngredient khác và nó hoạt động. Dữ liệu được truyền cho bộ điều khiển của tôi. :) Bây giờ tôi có thể tiếp tục làm việc để làm sạch mã của mình và tìm ra cách tích hợp mô hình thành phần vào biểu mẫu động của tôi và sau đó xử lý dữ liệu trong bộ điều khiển của tôi! Cảm ơn Darin rất nhiều. – papayt

Các vấn đề liên quan