Now I get a JsonString from a column of a dbTable, and then I need to map them into the classes I wrote. The Problem is that, when I use a for loop to map all the value in razor page, it's totally fine when I use @textBoxFor, but @DropDownListFor no.
this is my razor page code.
@model unitManager.Models.VM_PC_Unit_Mstr
@using unitManager.Models
@{
Layout = "~/Views/Shared/_PageLayout.cshtml";
ViewBag.Title = "Edit";
var controller = ViewContext.RouteData.Values["controller"].ToString();
var action = ViewContext.RouteData.Values["action"].ToString();
bool isCreate = action.EndsWith("Create", StringComparison.OrdinalIgnoreCase);
ViewBag.title = isCreate ? "Create" : "Edit";
}
<style>
.menu_item {
background-color:darkgray;
}
.sub_item{
background-color:azure;
}
</style>
<!-- Basic Inputs Validation start -->
<div class="card">
<div class="card-block">
<form id="main" method="post" @*action="/" novalidate=""*@>
@* Course Name *@
<div class="form-group row">
<label class="col-sm-1 col-form-label">Course Name</label>
<div class="col-sm-3">
@if (!isCreate)
{
@Html.TextBoxFor(n => n.unit_id, new { @class = "form-control", @readonly = "true" })
}
else
{
@Html.TextBoxFor(n => n.unit_id, new { @class = "form-control required", @required = "required" })
}
<span class="messages"></span>
</div>
<div>
@Html.ValidationMessageFor(n => n.unit_id, null, new { @class = "text-danger text-center" })
</div>
</div>
@{
if (Model.menu_obj.menus != null)
{
for (var i = 0; i < Model.menu_obj.menus.Count; i )
{
var item = Model.menu_obj.menus[i];
string menu_id = "menu-" i;
<div id="@menu_id" class="menu_item">
@* type *@
<div class="form-group row">
<label class="col-md-3 col-form-label">Type</label>
<div class="col-md-9">
<input id="@(menu_id "-type")" type="text" value="@item.type">
</div>
</div>
@* No *@
<div class="form-group row">
<label class="col-md-3 col-form-label">No</label>
<div class="col-md-9">
<input id="@(menu_id "-No")" type="text" value="@item.No">
</div>
</div>
@* tittle *@
<div class="form-group row">
<label class="col-md-3 col-form-label">Title</label>
<div class="col-md-9">
<input id="@(menu_id "-title")" type="text" value="@item.title">
</div>
</div>
@* url *@
<div class="form-group row">
<label class="col-md-3 col-form-label">Url</label>
<div class="col-md-9">
<input id="@(menu_id "-url")" type="text" value="@item.url">
</div>
</div>
@* subItem *@
<div class="form-group row">
<label class="col-md-3 col-form-label">SubItem</label>
<div class="col-md-9">
@if (item.content != null)
{
for (var j = 0; j < item.content.Count; j )
{
var subItem = item.content[j];
string sub_id = "m-" i "-sub-" j;
<div class="sub_item">
@* type *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Type</label>
<div class="col-sm-9">
@Html.TextBoxFor(p => p.menu_obj.menus[i].content[j].type)
@Html.DropDownListFor(p => p.menu_obj.menus[i].content[j].type, ModelSelectList.subType())
</div>
</div>
@* SubNo *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Intro</label>
<div class="col-sm-9">
<input id="@(sub_id "-SubNo")" type="text" value="@subItem.SubNo">
</div>
</div>
@* intro *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Intro</label>
<div class="col-sm-9">
<input id="@(sub_id "-intro")" type="text" value="@subItem.intro">
</div>
</div>
@* title *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Title</label>
<div class="col-sm-9">
<input id="@(sub_id "-title")" type="text" value="@subItem.title">
</div>
</div>
@* shortcut *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Shortcut</label>
<div class="col-sm-9">
<input id="@(sub_id "-shortcut")" type="text" value="@subItem.shortcut">
</div>
</div>
@* url *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Url</label>
<div class="col-sm-9">
<input id="@(sub_id "-url")" type="text" value="@subItem.url">
</div>
</div>
@* record_timing *@
<div class="form-group row">
<label class="col-sm-3 col-form-label">Record_timing</label>
<div class="col-sm-9">
<input id="@(sub_id "-recordtime")" type="text" value="@subItem.record_timing">
</div>
</div>
</div>
}
}
</div>
</div>
</div>
}
}
}
<div class="form-group row">
<div class="col-sm-4" style="display:flex;justify-content:flex-end">
<a type="button" class="btn btn-primary" style="color:white;margin:10px;" href="@Url.Action("Index","UnitMgr")">Cancel</a>
<button type="submit" class="btn btn-primary" style="color:white;margin:10px;">Submit</button>
</div>
</div>
</form>
</div>
</div>
<script>
$("div[id ^='menu-']").each(function () {
console.log($(this));
let menu_idx = $(this).attr("id").replace("menu-", "");
console.log(menu_idx);
$("input[id ^= 'm-" menu_idx "-sub-']").each(function () {
console.log("sub", $(this), $(this).val());
});
});
$(function () {
$(".select2").select2();
});//document ready
</script>
this is my controller action looks like
[HttpGet]
public ActionResult Menu(string unit_id)
{
VM_PC_Unit_Mstr model= PC_Unit_Mstr.getMenuByunitID(unit_id);
model.menu_obj = JsonConvert.DeserializeObject<Menu>(model.menus_json);
return View(model);
}
and the ViewModel I use
public class VM_PC_Unit_Mstr
{
public string unit_id { get; set; }
public string menus_json { get; set; }
public VM_Menu.Menu menu_obj { get; set; }
}
The problem I met is in here, which I can map the value with TextBoxFor successfully, but not dropDownListFor.
@Html.TextBoxFor(p => p.menu_obj.menus[i].content[j].type)
@Html.DropDownListFor(p => p.menu_obj.menus[i].content[j].type, ModelSelectList.subType())
And this is the result I get in the web page: This is the simple function I wrote to get the DropDownList :
public static SelectList subType()
{
List<SelectListItem> itemList = new List<SelectListItem>();
SelectListItem itemSpeaking = new SelectListItem
{
Value = "speaking",
Text = "speaking",
};
SelectListItem itemWords = new SelectListItem
{
Value = "words",
Text = "words",
};
SelectListItem itemGame = new SelectListItem
{
Value = "game",
Text = "game",
};
itemList.Add(itemSpeaking);
itemList.Add(itemWords);
itemList.Add(itemGame);
return new SelectList(itemList, "Value", "Text");
}
This is what VM_Menue is:
public class VM_Menu
{
#region MenuList (MenuListInfo)
public class MenuList
{
public string WelcomeImage { get; set; }
public string Menus { get; set; }
}
public class Menu
{
public string welcomeImg { get; set; }
public List<MenuData> menus { get; set; }
}
public class MenuData
{
public string type { get; set; } //video or game or conclusion
public string No { get; set; }
public string title { get; set; }
public string url { get; set; }
public List<SubItemData> content { get; set; }
}
public class SubItemData
{
public string type { get; set; } //speaking or words or game
public string SubNo { get; set; }
public string intro { get; set; }
public string title { get; set; }
public string shortcut { get; set; }
public string url { get; set; }
public float? record_timing { get; set; }
}
#endregion
}
At first, my purpose is to make a two level input/dropDownList tree, which allows user to edit dynamically, how many parent node user wants, below the current parent node, how many sub node user wants to edit, create or delete.
So, before this function I want to make, I firstly encounter this dropdownlist mapping problem with @html function.
Hope the intention and information I offer is enough and clear. Thank you all for reviewing my codes, it is a mess I know.
CodePudding user response:
I'm afraid you cannot set selected option with @Html.DropDownListFor
.You can try to foreach ModelSelectList.subType()
and add selected
to the option if the value is the same with menu_obj.menus[i].content[j].type
:
<select name="menu_obj.menus[@i].content[@j].type">
@foreach (var item in ModelSelectList.subType())
{
if (item.Text == Model.menu_obj.menus[i].content[j].type)
{
<option value[email protected] selected>@item.Text</option>
}
else
{
<option value[email protected]>@item.Text</option>
}
}
</select>
CodePudding user response:
ModelSelectList.subType()
@foreach (var item in ModelSelectList.subType()) { //
}