Is there any way to instruct the model binder to recreate the Currency object when a different option item is selected on the client?
You can add hidden fields in the form to pass the properties of Currency like:
<select id="currencySelect" class="form-select" asp-for="MyModel.Currency" onchange="updateCurrencyFields()">
@foreach (var currency in Model.AllCurrencies)
{
if (currency.Code == Model.MyModel.Currency.Code)
{
<option value="??????" data-numericcode="@currency.NumericCode"
data-code="@currency.Code" data-name="@currency.Name" selected="">
@currency.Name
</option>
}
else
{
<option value="??????" data-numericcode="@currency.NumericCode"
data-code="@currency.Code" data-name="@currency.Name">
@currency.Name
</option>
}
}
</select>
<input type="hidden" asp-for="MyModel.Currency.NumericCode" id="NumericCode" />
<input type="hidden" asp-for="MyModel.Currency.Code" id="Code"/>
<input type="hidden" asp-for="MyModel.Currency.Name" id="Name"/>
</div>
<button type="submit">Submit</button>
</form>
<script>
function updateCurrencyFields() {
var select = document.getElementById("currencySelect");
var numericcode = select.options[select.selectedIndex].getAttribute("data-numericcode");
var code = select.options[select.selectedIndex].getAttribute("data-code");
var name = select.options[select.selectedIndex].getAttribute("data-name");
document.getElementById("NumericCode").value = numericcode;
document.getElementById("Code").value = code;
document.getElementById("Name").value = name;
}
</script>
And code in the MyCurrencyPageModel like:
public class MyCurrencyPageModel : PageModel
{
private readonly ApplicationDbContext _context;
public MyCurrencyPageModel(ApplicationDbContext context)
{
_context = context;
}
[BindProperty]
public MyModel MyModel { get; set; }
public IEnumerable<Currency> AllCurrencies { get; set; }
public void OnGet()
{
AllCurrencies = _context.Currencies.ToList();
MyModel = new MyModel(Guid.NewGuid(), "Example Program", "Description", AllCurrencies.First());
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
MyModel.Id = Guid.NewGuid();
var item = _context.Currencies.Where(v=>v.Code ==MyModel.Currency.Code).FirstOrDefault();
MyModel.Currency = item;
_context.MyModels.Add(MyModel);
_context.SaveChanges();
return RedirectToPage("Index");
}
}
With the test result: