Lorsque la page charge, tout fonctionne bien. Mais lorsque je soumets le formulaire, mes listes déroulantes perdent les éléments sélectionnés précédents après la mise à jour de la page.
Comment puis-je modifier ma fonction pour initialiser les listes déroulantes et conserver les éléments précédents sélectionnés (sur les deux) s'ils existent.
Voici ma vue avec le javascript qui initialise mes listes déroulantes:
@model Models.Book @{ ViewBag.Title = "Index"; } @section scripts { <script type="text/javascript"> $(function() { $.getJSON("/Home/Books/List", function(data) { var items = "<option>--------------------</option>"; $.each(data, function(i, book) { items += "<option value='" + book.Value + "'>" + book.Text + "</option>"; }); $("#Books").html(items); }); $("#Books").change(function() { $.getJSON("/Home/Chapters/List/" + $("#Books> option:selected").attr("value"), function(data) { var items = "<option>--------------------</option>"; $.each(data, function(i, chapter) { items += "<option value='" + chapter.Value + "'>" + chapter.Text + "</option>"; }); $("#Chapters").html(items); }); }); }); </script> } @using (@Html.BeginForm("ListChapterContent", "Home")) { <div id="header"> <label for="Books">Books</label> <select id="Books" name="Books"></select> <label for="Chapters">Chapters</label> <select id="Chapters" name="Chapters" onchange="this.form.submit();"></select> </div>
Voici mon modèle:
public class Book { public string Translator{ get; set; } public string Edition{ get; set; } public List<Book> Books{ get; set; } public int SelectedBook { get; set; } public int SelectedChapter { get; set; } }
Utilisez les HtmlHelpers pour générer vos contrôles plutôt que créer manuellement votre html afin que vous obteniez une liaison de modèle à 2 voies. Vous en trouverez le plus simple si vous utilisez un modèle de vue
public class BookVM { [Required] public int? SelectedBook { get; set; } [Required] public int? SelectedChapter { get; set; } public SelectList BookList { get; set; } public SelectList ChapterList { get; set; } }
Manette
public ActionResult Create() { BookVM model = new BookVM(); ConfigureViewModel(model); return View(model); } private void ConfigureViewModel(BookVM model) { IEnumerable<Book> books = db.Books; model.BookList = new SelectList(books, "ID", "Name"); if (model.SelectedBook.HasValue) { IEnumerable<Chapter> chapters= db.Books.Where(c => c.BookId == model.SelectedBook.Value); model.ChapterList = new SelectList(chapters, "ID", "Name"); } else { model.ChapterList = new SelectList(Enumerable.Empty<SelectListItem>()); } }
Et dans la vue
@model BookVM @using (@Html.BeginForm()) { @Html.LabelFor(m => m.SelectedBook) @Html.DropDownListFor(m => m.SelectedBook, Model.BookList, "-Please select-") @Html.ValidationMessageFor(m => m.SelectedBook) @Html.LabelFor(m => m.SelectedChapter) @Html.DropDownListFor(m => m.SelectedChapter, Model.ChapterList) @Html.ValidationMessageFor(m => m.SelectedChapter) }
Ensuite, votre script devient (supprimez le premier)
var url = '@Url.Action("FetchChapters")'; // don't hard code url's var chapters = $('#SelectedChapter'); $('#SelectedBook').change(function() { if (!$(this).val()) { return; } $.getJSON(url, { id: $(this).val() }, function(data) { chapters.empty().append($('<option></option>').val('').text('-Please select-')); $.each(data, function(index, chapter) { subLocalities.append($('<option></option>').val(item.Value).text(item.Text)); }); }); });
Et votre méthode pour retourner le json serait
public JsonResult FetchSubLocalities(int ID) { var chapters= db.Books.Where(c => c.BookId == ID).Select(c => new { Value = c.ID, Name = c.Name }); return Json(chapters, JsonRequestBehavior.AllowGet); }
Et enfin dans la méthode POST, si vous devez retourner la vue
[HttpPost] public ActionResult Create(BookVM model) { if(!ModelState.IsValid) { ConfigureViewModel(model); return View(model); } ....
Reportez-vous également à ce DotNetFiddle pour un exemple similaire