Reputation: 1403
I am creating an MVC 5 web project that collects numerical data from the user. The majority of the fields are nullable decimals and I have a requirement to display them to various decimal places while maintaining the full precision when writing back to the database.
The view model has properties such as:
public decimal? TonnesOfFoo { get; set; }
public decimal? TonnesOfBar { get; set; }
The view itself renders the controls as:
@Html.TextBoxFor(model => model.TonnesOfFoo, "{0:N1}", new { @class = "form-control" })
@Html.TextBoxFor(model => model.TonnesOfBar, "{0:N3}", new { @class = "form-control" })
This works well and presents the data as needed however when the form is posted back I am writing the rounded values back to the database.
Is there any way around this without having "actual" and "display" properties in my view model and using jQuery to sync them all up? Is there some kind of editor template I could use to handle this situation?
UPDATE
Using the suggestion from M.Ob I have finally managed to get this working.
I am no longer using the in-line formatting, instead I am using two data attributes, one for the full precision and one for the number of decimal places required. For example :
@Html.TextBoxFor(model => model.TonnesOfFoo, new { @class = "form-control", data_fullprecision = Model.TonnesOfFoo, data_precision = 1 })
Then on document ready I loop through and manually apply the formatting using the jQuery Number Plugin:
$('input[data-fullprecision]').each(function () {
var selector = '#' + this.id;
var precision = parseInt($(selector).data('precision'));
var fullprecisionValue = $(selector).data('fullprecision');
if ($.isNumeric(fullprecisionValue)) {
var roundedValue = $.number(fullprecisionValue, precision, '.', '');
$(selector).val(roundedValue);
}
});
I am not sure if the above is overkill but I needed a way to present the data in the correct format if any validation errors occurred in the controller, without this the un-rounded values were displayed along with the validation messages.
I use a similar scripts to map the values to the data attributes when the user changes a value and finally to map the full precision numbers to the text boxes before the form is submitted.
Upvotes: 2
Views: 1089
Reputation: 2530
I would use a view model that contains the original values and the rounded displayed values, when persisting back to the DB, compare the original values with the rounded values, if a value hasn't changed persist the original value, if it has persist the new value.
I'm of the opinion this would be the easiest solution to this problem, although performance might not be the best.
Other solutions might be to look at using Knockout on the client, and tracking which values have changed, and then only saving those values
Upvotes: 0
Reputation: 1837
There may be a more elegant way, but here is one idea:
You could do something like this: store your full precision value in a data- attribute of your textbox. Then, when the user changes the text, us JS to update the data- attribute to the new value. Upon form post, you can then have a JS function update your text boxes' values with the data- values before the submit occurs. This way, all of your new(updated) values and your untouched textbox values will be properly posted over not rounded.
@Html.TextBoxFor(model => model.TonnesOfFoo, "{0:N1}", new { @class = "form-control", data_fullprecision = Model.TonnesOfFoo })
Upvotes: 1