2012-02-16 68 views
5

我一直在嘗試幾個星期,遵循一些關於如何創建一個動態表單的教程,以便給表單添加另一個「成分」。這是我試圖遵循的文章。 http://www.joe-stevens.com/2011/07/24/asp-net-mvc-2-client-side-validation-for-dynamic-fields-added-with-ajax/MVC 3動態表單使用ViewModel

現在我只是在使用添加鏈接添加多個recipeIngredients,但是我需要在單擊鏈接時添加「ingredientName」和「recipeIngredient」數量。 我的問題是,當我運行應用程序時,recipeingredient的窗體有一個0而不是實際的文本框。當我點擊添加新的成分,我能夠得到一個文本框來添加,但是當我輸入一個數量並點擊保存時,模型數據不會被傳遞給控制器​​..

我只是不知道在哪裏首先解決這個問題,我不確定我是否應該使用視圖模型,或者如果我對此完全錯誤。這是我的數據庫圖http://i44.tinypic.com/xp1tog.jpg

這裏是我的CreateView的:

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

我對recipeingredient editortemplateview:

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

     } 
    } 

MY與控制器方法:

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

我的視圖模型:

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

如果沒有幫助我的問題了,請讓我知道所需的任何其他信息。這真的讓我發瘋,所以我期待着任何幫助,我可以得到 謝謝!

我還想提一下,控制器的post方法createfullrecipe是一個預先定義的列表,它工作時,我不擔心給用戶添加另一種成分的能力,而我只是默認形式有兩種成分我的觀點有這個代碼來創建它們。我真正想要做的就是讓viewmodel將表單數據傳遞給控制器​​,並且我可以像處理createfullrecipe控制器方法那樣處理數據。

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

這裏是我的模型類:

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

我在這個博客文章中談論這個問題:http://www.jasoncavett.com/2011/03/using-unobtrusive-jquery-validation.html – JasCav 2012-02-16 17:01:58

+0

現在我不知道驗證是否是我最大的問題。我不能得到動態的形式發送數據到我的控制器。現在,例如,如果我輸入食譜名稱,那麼傳遞給我的控制器的viewmodel中就存在非ajax東西。 – papayt 2012-02-16 17:12:01

回答

13

有許多與你的代碼問題。我更願意一步一步來說明一個可以適應您需求的簡化示例。

型號:

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

控制器:

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

視圖(~/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> 
} 

編輯模板(~/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

感謝您的幫助,我真的很感激。我更新了我的文章,以包括我現有的可能有助於解答的模型。我還可以使用一些幫助來確定我是否應該將規範化表格Ingredient和recipeIngredient合併爲一個表格/模型以簡化事情?我也用更簡潔的方法更新了我的js和views,但是controller post方法仍然沒有在viewModel中傳入我的表單數據。我認爲這與我的模型如何設置有關? – papayt 2012-02-16 17:04:10

+0

@papayt,你試過我的代碼嗎?正如我所說,你的問題很多。例如,你有'使用(Html.BeginCollectionItem(「RecipeIngedients」))'而正確的是'使用(Html.BeginCollectionItem(「RecipeIngredients」))'只是因爲你的屬性被稱爲'RecipeIngredients'而不是'RecipeIngedients'。另一個問題是您的編輯器模板的名稱和位置。所以我建議你使用我的代碼作爲擴展的基礎。 – 2012-02-16 17:35:12

+0

哇,我甚至沒有意識到我有一個錯字(Html.BeginCollectionItem(「RecipeIngedients」)),謝謝!我將我的重命名編輯器模板移至您推薦的文件夾中。而且...太棒了!我只是測試了我的代碼的動態recipeIngredient部分,並添加了另一個recipeIngredient,它可以工作。數據傳遞給我的控制器。 :)現在我可以繼續清理我的代碼,並確定如何將成分模型集成到我的動態表單中,然後處理控制器中的數據!非常感謝Darin。 – papayt 2012-02-16 17:56:57