7

Html.BeginCollectionItem 도우미를 사용하여 컬렉션을 통과하는 부분보기 : Submit same Partial View called multiple times data to controller?내가 여기에 스티븐 뮈크에서 답변을 이해하는 작은 프로젝트 만든

는 거의 모든 작품을. 자바 스크립트는 Partial View에서 새로운 필드를 추가하고 부분 뷰의 컨트롤러 메소드에 의해 삽입 된 "temp"값으로 모델에 바인딩되었음을 알 수 있습니다.

그러나 새 필드를 제출하면 AddRecord() 메서드가 모델이 전달되지 않는다는 예외 ("개체 참조가 개체 인스턴스로 설정되지 않음")를 표시하는 예외를 throw합니다.

또한 페이지 원본을 볼 때 BeginCollectionItem 도우미는 기존 레코드를 표시하는 기본보기의 테이블 주위에 숨겨진 태그를 삽입하지만 자바 스크립트가 추가하는 새 필드는 숨겨지지 않습니다.

내가 뭘 잘못하고 있니? 나는 이것에 아주 새롭다 당신의 끈기를위한 감사합니다!

내 주요보기 :

@model IEnumerable<DynamicForm.Models.CashRecipient> 

@using (Html.BeginForm("AddDetail", "CashRecipients", FormMethod.Post)) 
{ 
    @Html.AntiForgeryToken() 
    <div id="CSQGroup"> 
    </div> 
} 

<div> 
    <input type="button" value="Add Field" id="addField" onclick="addFieldss()" /> 
</div> 

<script> 
    function addFieldss() 
    { 
     //alert("ajax call"); 
     $.ajax({ 
      url: '@Url.Content("~/CashRecipients/RecipientForm")', 
      type: 'GET', 
      success:function(result) { 
       //alert("Success"); 
       var newDiv = document.createElement("div"); 
       var newContent = document.createTextNode("Hi there and greetings!"); 
       newDiv.appendChild(newContent); 
       newDiv.innerHTML = result; 
       var currentDiv = document.getElementById("div1"); 
       document.getElementById("CSQGroup").appendChild(newDiv); 
      }, 
      error: function(result) { 
       alert("Failure"); 
      } 
     }); 
    } 
</script> 

내 부분보기 :

@model DynamicForm.Models.CashRecipient 
@using HtmlHelpers.BeginCollectionItem 

@using (Html.BeginCollectionItem("recipients")) 
{ 
    <div class="editor-field"> 
     @Html.LabelFor(model => model.Id) 
     @Html.LabelFor(model => model.cashAmount) 
     @Html.TextBoxFor(model => model.cashAmount) 
     @Html.LabelFor(model => model.recipientName) 
     @Html.TextBoxFor(model => model.recipientName) 
    </div> 
    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="Save" class="btn btn-default" /> 
     </div> 
    </div> 
} 

내 모델 : 내 컨트롤러에서

public class CashRecipient 
{ 
    public int Id { get; set; } 
    public string cashAmount { get; set; } 
    public string recipientName { get; set; } 
} 

:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult AddDetail([Bind(Include = "Id,cashAmount,recpientName")] IEnumerable<CashRecipient> cashRecipient) 
{ 
    if (ModelState.IsValid) 
    { 
     foreach (CashRecipient p in cashRecipient) { 
      db.CashRecipients.Add(p); 
     } 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 

    } 

    return View(cashRecipient); 
} 

public ActionResult RecipientForm() 
{ 
    var data = new CashRecipient(); 
    data.cashAmount = "temp"; 
    data.recipientName = "temp"; 
    return PartialView(data); 
} 
+1

'Html.BeginCollectionItem()'을 하나의 객체에 적용된 콜렉션 인 모델에 적용 할 수 없습니다. 그리고 당신의 견해는 typeof'CashRecipient '에 대한 편집 가능한 컨트롤조차도 생성하지 않습니다.코드에는 여러 가지 오류가 있지만 정확히 여기서 무엇을하려고하는지 명확하지 않습니다. 새로운'CashRecipient'를 동적으로 추가 (및/또는 제거)하고 컬렉션을 포스트 할 수있는 양식을 원하십니까? –

+0

나는 Brajesh가 너를 도와 준 질문에서 똑같은 일을하려하고있다. 나는 그의 모델 AdminProductDetailModel 대신에 CashRecipient를 제외하고는 그와 동일한 자바 스크립트와 대략 동일한 부분보기 코드를 사용하고있다. 추가되는 각 컨트롤은 단일 객체 용입니다. 모델 자체는 콜렉션이 아닙니다. BeginCollectionItem이 컬렉션으로 여러 컨트롤의 데이터를 래핑했다고 생각했습니다 ... 아마 오해했을 것입니다. 나 좀 도와 줄 수있어? –

+1

내 첫 코멘트에서 쿼리에 대답 :) 그리고 왜 당신은'DisplayFor()'를 사용하고 있는데 그냥 텍스트를 렌더링하고 아무것도 편집 할 수 없다는 것을 의미합니다. –

답변

14

먼저 편집 할 항목을 나타내는보기 모델을 만들어 시작합니다. 나는

public class CashRecipientVM 
{ 
    public int? ID { get; set; } 
    public decimal Amount { get; set; } 
    [Required(ErrorMessage = "Please enter the name of the recipient")] 
    public string Recipient { get; set; } 
} 

는 그런 부분보기 (말) _Recipient.cshtml

@model CashRecipientVM 
<div class="recipient"> 
    @using (Html.BeginCollectionItem("recipients")) 
    { 
     @Html.HiddenFor(m => m.ID, new { @class="id" }) 
     @Html.LabelFor(m => m.Recipient) 
     @Html.TextBoxFor(m => m.Recipient) 
     @Html.ValidationMesssageFor(m => m.Recipient) 
     @Html.LabelFor(m => m.Amount) 
     @Html.TextBoxFor(m => m.Amount) 
     @Html.ValidationMesssageFor(m => m.Amount) 
     <button type="button" class="delete">Delete</button> 
    } 
</div> 
를 작성 (필수 속성으로 다른 검증 및 디스플레이를 추가) cashAmount는 금전적 가치입니다 있으리라 믿고있어, 그래서 때문에 소수이어야한다

및 해당 부분을 반환하는 방법

public PartialViewResult Recipient() 
{ 
    return PartialView("_Recipient", new CashRecipientVM()); 
} 

그런 다음 기본 GET metho d를

public ActionResult Create() 
{ 
    List<CashRecipientVM> model = new List<CashRecipientVM>(); 
    .... // add any existing objects that your editing 
    return View(model); 
} 

되며 해당 뷰는

@model IEnumerable<CashRecipientVM> 
@using (Html.BeginForm()) 
{ 
    <div id="recipients"> 
     foreach(var recipient in Model) 
     { 
      @Html.Partial("_Recipient", recipient) 
     } 
    </div> 
    <button id="add" type="button">Add</button> 
    <input type="submit" value="Save" /> 
} 

되며 항목을 삭제하기 위해 새로운 CashRecipientVM

var url = '@Url.Action("Recipient")'; 
var form = $('form'); 
var recipients = $('#recipients'); 
$('#add').click(function() { 
    $.get(url, function(response) { 
     recipients.append(response); 
     // Reparse the validator for client side validation 
     form.data('validator', null); 
     $.validator.unobtrusive.parse(form); 
    }); 
}); 

하고 스크립트의 HTML을 추가하는 스크립트를 포함

$('.delete').click(function() { 
    var container = $(this).closest('.recipient'); 
    var id = container.find('.id').val(); 
    if (id) { 
     // make ajax post to delete item 
     $.post(yourDeleteUrl, { id: id }, function(result) { 
      container.remove(); 
     }.fail(function (result) { 
      // Oops, something went wrong (display error message?) 
     } 
    } else { 
     // It never existed, so just remove the container 
     container.remove(); 
    } 
}); 

그리고 폼이 다시 게시됩니다

public ActionResult Create(IEnumerable<CashRecipientVM> recipients) 
+0

어떻게 제거합니까? –

+1

@TravisTubbs, 컬렉션에서 항목을 삭제하기위한 업데이트보기 (새 항목에 대한 클라이언트 측 유효성 검사를받을 수 있도록 유효성 검사기를 다시 파쇄) –

+0

덕분에 스티븐!로드가 도움이되었습니다 –

관련 문제