I have a Razor modal that gets data from the BE
Here is model
public class LocationServiceEditDto: EntityDto<int?>
{
public int ServiceId { get; set; }
public int? LocationId { get; set; }
public decimal? Cost { get; set; }
public int? MaterialUomId { get; set; }
public string MaterialUomName { get; set; }
public string LocationName => Location?.Name;
[JsonIgnore]
public LocationNameDto Location { get; set; }
public ICollection<LocationServicePriceDto> LocationServicePrices { get; set; }
}
at BE I populate collection of LocationServicePrices
And then in View, I show it like this
<div class="modal-body box-wrap">
<form role="form" novalidate class="form-validation" name="ServicePriceInformationsForm">
<input type="hidden" asp-for="Id"/>
<input type="hidden" asp-for="ServiceId"/>
<div class="form-group">
<label class="required-label">@L("Location")</label>
<select class="form-control" required asp-for="LocationId">
<option value="">@L("SelectALocation")</option>
@if (Model.LocationId.HasValue)
{
<option selected value="@Model.LocationId">@Model.LocationName</option>
}
</select>
</div>
<div class="form-group">
<label class="required-label">@L("MaterialUom")</label>
<select class="form-control" asp-for="MaterialUomId" id="ServicePrice_MaterialUomId">
<option value="">Select an option</option>
@if (Model.MaterialUomId > 0)
{
<option value="@Model.MaterialUomId">@Model.MaterialUomName</option>
}
</select>
</div>
<div class="form-group">
<label>@L("Cost")</label>
<input class="form-control" type="text" asp-for="Cost" data-rule-number="true" data-rule-min="0" data-rule-max="@AppConsts.MaxDecimalDatabaseLength">
</div>
@foreach (var tier in @Model.LocationServicePrices)
{
<div class="form-group">
<label>@tier.PricingTierName</label>
<input class="form-control" type="text" asp-for="@tier.PricePerUnit" data-rule-number="true" data-rule-min="0" data-rule-max="@AppConsts.MaxDecimalDatabaseLength">
</div>
}
</form>
</div>
I want to update every input in foreach and make @Model.LocationServicePrices
updated.
For now, when I enter values and send data to BE, collection is null
I saving data like this in .js
file
this.save = function () {
if (!_$form.valid()) {
_$form.showValidateMessage();
return;
}
var servicePrice = _$form.serializeFormToObject();
_modalManager.setBusy(true);
_serviceService.editLocationService(servicePrice).done(function () {
abp.notify.info('Saved successfully.');
_modalManager.close();
abp.event.trigger('app.createOrEditServicePriceModalSaved');
}).always(function () {
_modalManager.setBusy(false);
});
};
Code for serializeFormToObject
method
$.fn.serializeFormToObject = function () {
var $form = $(this);
var fields = $form.find('[disabled]');
fields.prop('disabled', false);
var json = $form.serializeJSON();
fields.prop('disabled', true);
return json;
};
How I can fix this?
Not sure how does your whole js code work, but model binding system binds the property by name. If your backend receives form data, due to the LocationServicePrices
is a list model, you need pass them by name like:name="LocationServicePrices[@i].PricePerUnit"
.
@{
int i = 0;
}
@foreach (var tier in @Model.LocationServicePrices)
{
<div class="form-group">
<label>@tier.PricingTierName</label>
<input class="form-control" type="text" asp-for="@tier.PricePerUnit"
name="LocationServicePrices[@i].PricePerUnit" data-rule-number="true" data-rule-min="0" data-rule-max="@AppConsts.MaxDecimalDatabaseLength">
</div>
i++;
}
If your backend receives json string, the correct json should be:
{
"Id": "",
"ServiceId": "2031",
"LocationId": "2",
"MaterialUomId": "6",
"Cost": "123",
"LocationServicePrices": [
{ "PricePerUnit": "1"},
{ "PricePerUnit": "2"},
{"PricePerUnit": "3"},
{"PricePerUnit": "4"},
{"PricePerUnit": "5" }
]
}
UPDATE:
For how to generate the json string. You could use the js code below:
@model LocationServiceEditDto
<div class="modal-body box-wrap">
<form role="form" novalidate class="form-validation" name="ServicePriceInformationsForm">
<input type="hidden" asp-for="Id" />
<input type="hidden" asp-for="ServiceId" />
<div class="form-group">
<select class="form-control" required asp-for="LocationId">
<option value="">sssss</option>
<option value="1">aa</option>
<option value="2">bb</option>
<option value="3">cc</option>
</select>
</div>
<div class="form-group">
<select class="form-control" asp-for="MaterialUomId" id="ServicePrice_MaterialUomId">
<option value="">Select an option</option>
@if (Model.MaterialUomId > 0)
{
<option value="@Model.MaterialUomId">@Model.MaterialUomName</option>
}
</select>
</div>
<div class="form-group">
<input class="form-control" type="text" asp-for="Cost" data-rule-number="true" data-rule-min="0" data-rule-max="7">
</div>
@{
int i = 0;
}
@foreach (var tier in @Model.LocationServicePrices)
{
<div class="form-group">
<label>@tier.PricingTierName</label>
<input class="form-control" type="text" asp-for="@tier.PricePerUnit"
name="LocationServicePrices[@i].PricePerUnit" data-rule-number="true" data-rule-min="0" data-rule-max="7">
</div>
i++;
}
</form>
</div>
@section Scripts
{
<script>
var formData = {};
$('form[name="ServicePriceInformationsForm"]').serializeArray().forEach(function (item) {
formData[item.name] = item.value;
});
// Convert LocationServicePrices data to JSON array
formData["LocationServicePrices"] = [];
$('.form-group input[id$="PricePerUnit"]').each(function () {
formData["LocationServicePrices"].push({ "PricePerUnit": $(this).val() });
});
console.log(formData)
console.log(JSON.stringify(formData))
</script>
}