J'ai suivi l'approche indiquée dans les blogs ci-dessus et j'ai ajouté quelques détails qui pourraient être utiles à certains - en particulier parce que je voulais ajouter dynamiquement un nombre quelconque de lignes mais je ne voulais pas utiliser AJAX pour le faire (je voulais que le formulaire ne soit soumis que dans le message). Je ne voulais pas non plus me soucier du maintien des identifiants séquentiels. Je capturais une liste de dates de début et de fin :
Voir le modèle :
public class WhenViewModel : BaseViewModel {
public List<DateViewModel> Dates { get; set; }
//... Other properties
}
Date de début / fin Modèle de vue :
public class DateViewModel {
public string DateID { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
Puis les utiliser dans la page (avec le sélecteur de date) :
<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>
Comme le décrit l'article du blog dont le lien figure dans l'article de @ErikTheVikings ci-dessus, la collection est créée par l'élément caché répété : @Html.Hidden("Dates.Index", d.DateID)
pour chaque entrée de la collection sur la page.
Je voulais ajouter arbitrairement des rangs sans utiliser AJAX pour renvoyer les données au serveur, ce que j'ai fait en créant un div caché contenant un modèle d'un "rang" / élément dans la collection :
Ligne "Modèle" cachée :
<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>
J'ai ensuite utilisé jQuery qui clone le modèle, fournit un identifiant aléatoire à utiliser pour une nouvelle rangée et ajoute la rangée clonée maintenant visible à la div qui la contient :
jQuery pour compléter le processus :
<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>
Exemple JSFiddle du résultat : http://jsfiddle.net/mdares/7JZh4/