MVC 4 목록 모델 바인딩은 어떻게 작동합니까?
양식의 입력 세트를 List
MVC 4에서 바인딩하려면 input
name
속성에 대한 다음 명명 규칙 이 작동 한다는 것을 알고 있습니다.
<input name="[0].Id" type="text" />
<input name="[1].Id" type="text" />
<input name="[2].Id" type="text" />
하지만 모델 바인더가 얼마나 용서하는지 궁금합니다. 예를 들어, 다음은 어떻습니까?
<input name="[0].Id" type="text" />
<input name="[3].Id" type="text" />
<input name="[8].Id" type="text" />
모델 바인더는 이것을 어떻게 처리합니까? List
길이가 9 인 a 에 null을 바인딩 합니까? 아니면 여전히 List
길이 3에 바인딩 됩니까? 아니면 완전히 질식할까요?
내가 신경 쓰는 이유
사용자가 양식에 행을 추가하고 양식에서 행을 삭제할 수있는 동적 양식을 구현하고 싶습니다. 따라서 사용자가 총 8 개 행 중 2 번째 행을 삭제하면 모든 후속 입력의 번호를 다시 매겨 야하는지 알고 싶습니다.
컬렉션과 함께 사용하기위한 특정 와이어 형식이 있습니다. 이것은 Scott Hanselman의 블로그에서 논의됩니다.
Phil Haack의 또 다른 블로그 항목은 여기에 대해 설명합니다.
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
마지막으로 여기에서 원하는 작업을 정확히 수행하는 블로그 항목 :
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
위의 블로그에 링크 된이 접근 방식을 따랐고 일부 사용자에게 도움이 될 수있는 몇 가지 세부 정보를 추가했습니다. 게시물). 또한 순차 ID 유지에 대해 걱정하고 싶지 않았습니다. 시작일과 종료일 목록을 캡처했습니다.
모델보기 :
public class WhenViewModel : BaseViewModel {
public List<DateViewModel> Dates { get; set; }
//... Other properties
}
시작 / 종료 날짜보기 모델 :
public class DateViewModel {
public string DateID { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
그런 다음 페이지에서 사용 (datepicker 사용) :
<div class="grid-8-12 clear" id="DatesBlock">
@{
foreach (DateViewModel d in Model.Dates) {
@:<div class="grid-5-12 left clear">
@Html.Hidden("Dates.Index", d.DateID)
@Html.Hidden("Dates[" + d.DateID + "].DateID", d.DateID) //ID again to populate the view model
@Html.TextBox("Dates[" + d.DateID + "].StartDate",
d.StartDate.Value.ToString("yyyy-MM-dd"))
@:</div>
@:<div class="grid-5-12">
@Html.TextBox("Dates[" + d.DateID + "].EndDate",
d.EndDate.Value.ToString("yyyy-MM-dd"))
@:</div>
<script type="text/javascript">
$('input[name="Dates[@d.DateID].StartDate"]')
.datepicker({ dateFormat: 'yy-mm-dd'});
$('input[name="Dates[@d.DateID].EndDate"]')
.datepicker({dateFormat: 'yy-mm-dd'});
</script>
}
}
</div>
<a href="#" onclick="AddDatesRow()">Add Dates</a>
위의 @ErikTheVikings 게시물에 링크 된 블로그 게시물이 설명했듯이 컬렉션은 @Html.Hidden("Dates.Index", d.DateID)
페이지의 컬렉션에있는 각 항목에 대해 반복되는 숨겨진 요소에 의해 생성됩니다 .
AJAX를 사용하지 않고 임의로 행을 추가하여 데이터를 서버에 다시 게시하고 싶었습니다.이 경우 컬렉션에 하나의 "행"/ 항목의 템플릿을 포함하는 숨겨진 div를 만들었습니다.
숨겨진 "템플릿"행 :
<div id="RowTemplate" style="display: none">
<div class="grid-5-12 clear">
@Html.Hidden("Dates.Index", "REPLACE_ID")
@Html.Hidden("Dates[REPLACE_ID].DateID", "REPLACE_ID")
@Html.TextBox("Dates[REPLACE_ID].StartDate", "")
</div>
<div class="grid-5-12">
@Html.TextBox("Dates[REPLACE_ID].EndDate", "")
</div>
</div>
그런 다음 템플릿을 복제하고 새 행에 사용할 임의의 ID를 제공하고 지금 보이는 복제 된 행을 위의 포함 div에 추가하는 jQuery를 사용했습니다.
프로세스를 완료하는 jQuery :
<script type="text/javascript">
function AddDatesRow() {
var tempIndex = Math.random().toString(36).substr(2, 5);
var template = $('#RowTemplate');
var insertRow = template.clone(false);
insertRow.find('input').each(function(){ //Run replace on each input
this.id = this.id.replace('REPLACE_ID', tempIndex);
this.name = this.name.replace('REPLACE_ID', tempIndex);
this.value = this.value.replace('REPLACE_ID', tempIndex);
});
insertRow.show();
$('#DatesBlock').append(insertRow.contents());
//Attach datepicker to new elements
$('input[name="Dates['+tempIndex+'].StartDate"]')
.datepicker({dateFormat: 'yy-mm-dd' });
$('input[name="Dates['+tempIndex+'].EndDate"]')
.datepicker({dateFormat: 'yy-mm-dd' });
}
</script>
결과의 JSFiddle 예 : http://jsfiddle.net/mdares/7JZh4/
다음과 같은 동적 목록이 있습니다.
<ul id="okvedList" class="unstyled span8 editableList">
<li>
<input data-val="true" data-val-required="The Guid field is required." id="Okveds_0__Guid" name="Okveds[0].Guid" type="hidden" value="2627d99a-1fcd-438e-8109-5705dd0ac7bb">
--//--
</li>
따라서 행 (li 요소)을 추가하거나 제거 할 때 항목을 다시 정렬해야합니다.
this.reorderItems = function () {
var li = this.el_list.find('li');
for (var i = 0; i < li.length; i++) {
var inputs = $(li[i]).find('input');
$.each(inputs, function () {
var input = $(this);
var name = input.attr('name');
input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + i + ']'));
var id = input.attr('id');
input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + i + '__'));
});
}
};
this list placed into simple Html.BeginFrom from clientside and like List in action parameter on serverside
I also facing similar problem in the past, and I use KnockoutJS to handle such scenario.
Basically, Knockout send the collection in a JSON string, and I deserialized them in my controller.
For more info : http://learn.knockoutjs.com/#/?tutorial=collections
I got little problem, when i using Chrome Browser and click the back button, and i find the input with type="hidden" when dynamically set values didn't handled properly by the Chrome Browser.
maybe we can change
<input type="hidden" name="Detes.Index" value="2016/01/06" />
to
<div style="display: none">
<input type="text" name="Detes.Index" value="2016/01/06" />
</div>
Form more info: Chrome doesn't cache hidden form field values for use in browser history http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
참고URL : https://stackoverflow.com/questions/14822615/how-does-mvc-4-list-model-binding-work
'program tip' 카테고리의 다른 글
Python의 개인 생성자 (0) | 2020.12.09 |
---|---|
로지스틱 회귀에서 예측에 대한 신뢰 구간 (0) | 2020.12.09 |
충돌을 미리 알려주는 일종의 'git rebase --dry-run'이 있습니까? (0) | 2020.12.09 |
스크립트가 tty에서 실행 중인지 확인하는 방법은 무엇입니까? (0) | 2020.12.09 |
SaveOrUpdate 대 업데이트 및 NHibernate에서 저장 (0) | 2020.12.09 |