2012-02-16 2 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 사용

지금 당장이라면 add 링크를 사용하여 여러 recipeIngredients를 추가하는 중입니다. 링크를 클릭 할 때 추가 할 수있는 "ingredientName"및 "recipeIngredient"Amount가 있어야합니다. 제 문제는 앱을 실행할 때 recipeingredient의 양식에 실제 텍스트 상자 대신 0이 있다는 것입니다. 새 재료 추가를 클릭하면 추가 할 텍스트 상자를 얻을 수 있지만 금액을 입력하고 저장을 클릭하면 컨트롤러에 모델 데이터가 전달되지 않습니다 ..

나는 어디 까지나 알지 못합니다. 이걸 고치기 시작하면, 내가 뷰 모델을 사용해야하는지, 아니면 완전히 잘못된 생각을하고 있는지 확실하지 않습니다. 다음은 데이터베이스 다이어그램 http://i44.tinypic.com/xp1tog.jpg입니다. 하는 recipeIngredient에 대한

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

@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()); 
    } 
012,351,641 여기

내 CreateView입니다

내보기 모델 :

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

알려 주시기 바랍니다 내 문제를 도와 필요한 다른 정보가있는 경우. 이것은 내가 정말 미쳐서 내가 얻을 수있는 어떤 도움을 고대합니다. 고마워요!

컨트롤러 게시 메서드 createfullrecipe는 미리 정의 된 목록이며 사용자가 다른 재료를 추가 할 수있는 것에 대해 걱정할 필요가 없을 때 효과가 있었음을 언급하고자합니다. 오히려 양식에 2 가지 성분을 기본으로 설정했습니다. 내 의견에는이 코드를 주석으로 작성하여 코드를 작성했습니다. 필자가 정말로하고 싶은 것은 viewmodel이 폼 데이터를 컨트롤러에 넘겨 주며 createfullrecipe 컨트롤러 메소드처럼 데이터를 처리 할 수 ​​있습니다. 코드에 문제가 많이 있습니다

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

+0

바로 지금 유효성 검사가 가장 큰 문제인지 확실하지 않습니다. 데이터를 내 컨트롤러로 보내려면 동적 양식을 가져올 수 없습니다. 예를 들어 레시피 이름을 입력하면 비 아약스 물건, 내 컨트롤러에 전달 된 뷰 모델에 존재합니다. – papayt

답변

13

: 여기

@* @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 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를 업데이트했지만 컨트롤러 포스트 메서드는 여전히 viewModel에 전달 된 폼 데이터를 가지고 있지 않습니다. 내 모델이 설치되는 방식과 관련이 있다고 가정합니다. – papayt

+0

@papayt, 내 코드를 사용해 보셨습니까? 내가 말했듯이 당신에게는 많은 문제가 있습니다. 예를 들어'Html.BeginCollectionItem ("RecipeIngedients"))'를 사용하는 반면에'RecipeIngedients'가 아니라 단순히'RecipeIngredients'라는 속성을 사용하기 때문에'Html.BeginCollectionItem ("RecipeIngredients"))'를 사용하는 것입니다. 또 다른 문제점은 편집기 템플리트의 이름과 위치입니다. 따라서 내 코드를 확장을위한 기반으로 사용하는 것이 좋습니다. –

+0

O Wow 나는 Html.BeginCollectionItem ("RecipeIngedients")와 오타가 있음을 깨닫지 못했다. 감사합니다! 내 이름을 바꾼 편집기 템플릿을 권장 폴더로 옮겼습니다. 그리고 ... 굉장해! 나는 다른 레시피 구성 요소를 추가 할 수있는 기능으로 내 동적 레시피 부분 코드를 테스트했습니다. 작동합니다. 데이터가 내 컨트롤러로 전달됩니다. :) 이제 코드를 정리하고 동적 모델에 성분 모델을 통합 한 다음 컨트롤러에서 데이터를 처리하는 방법을 알아낼 수 있습니다. 다린, 정말 고마워. – papayt