Reputation: 7525
I am trying to display and edit fractions in an MVC application. Previously in WPF I used the concept of a converter to take a double and format it as a fraction for the user and then take the users input and covert it back to a fraction. What would be the best way to do this in a Razor view?
Upvotes: 0
Views: 793
Reputation: 6679
I Admit it was harder than I thought. I'm still not sure if it's the best way to do it or not, but it works.
I defined a super simple Model:
public class MyModel
{
[DataType("Fraction")] //It's important to define DataType
public double MyDouble { get; set; }
}
and here is my simple controller:
public class HomeController : Controller
{
public ActionResult Index()
{
MyModel ViewModel = new MyModel { MyDouble = 0.06 };
return View(ViewModel);
}
[HttpPost]
public ActionResult Index(MyModel model)
{
// Update db.
// Do what you want to do.
return View(model);
}
}
Index view (\Views\Home\Index.cshtml):
@model MvcApplication1.Models.MyModel
@{ViewBag.Title = "Index";}
@Html.DisplayFor(m => m.MyDouble)
<br />
@using (Html.BeginForm("Index", "Home"))
{
@Html.EditorFor(m => m.MyDouble)
<input type="submit" value="Submit" />
}
<script type="text/javascript">
function fraction_changing(hiddenFieldId, numeratorId, denominatorId) {
var numeratorValue = document.getElementById(numeratorId).value;
var denominatorValue = document.getElementById(denominatorId).value;
var hiddenField = document.getElementById(hiddenFieldId);
hiddenField.value = numeratorValue / denominatorValue;
}
</script>
You will find out about the above Javascript code in just a minute.
Display Template is also so easy. I just used Fraction class (By Syed Mehroz Alam) to convert double values to Fraction.
As you know, Templates (which are Partial Views) should be placed in "DisplayTemplates" and "EditorTemplates" folders under "Views" folder. I prefer to put them in "Views\Shared\" so all other Views are able to use it.
Fraction.cshtml (\Views\Shared**DisplayTemplates\Fraction.cshtml**)
@using Mehroz // Fraction class lives in Mehroz namespace
@inherits System.Web.Mvc.WebViewPage<double>
@{
Fraction fraction = new Fraction(Model);
}
@fraction.Numerator / @fraction.Denominator
Let's now take a look at the tricky part, which is Edit Template.
So here is Fraction.cshtml (\Views\Shared**EditorTemplates\Fraction.cshtml**)
@using Mehroz
@inherits System.Web.Mvc.WebViewPage<double>
@{
Fraction fraction = new Fraction(Model);
string numeratorStr = fraction.Numerator.ToString();
string denominatorStr = fraction.Denominator.ToString();
string unifier = Guid.NewGuid().ToString().Replace('-', '_');
string hiddenFieldElementId = string.Format("hiddenField{0}", unifier);
string numeratorElementId = string.Format("numerator{0}", unifier);
string denominatorElementId = string.Format("denominator{0}", unifier);
string onchangingFunctionSyntax =
string.Format("fraction_changing('{0}', '{1}', '{2}')",
hiddenFieldElementId,
numeratorElementId,
denominatorElementId);
}
@Html.HiddenFor(m => m, new { id = hiddenFieldElementId })
@Html.TextBox("Numerator", numeratorStr,
new { id = numeratorElementId, onchange = onchangingFunctionSyntax }) /
@Html.TextBox("Denominator", denominatorStr,
new { id = denominatorElementId, onchange = onchangingFunctionSyntax })
What this template really do is:
Because Javascript code needs unique Id to get an element by document.getElementById(id)
, our Edit Template has to generate these unique IDs for related elements.
You can download the code here: http://sdrv.ms/MlyDI2
Upvotes: 1
Reputation: 6679
The best and cleanest way to solve your issue is to develop a Display/Edit Template. Here is a nice article about it:
Overriding DisplayFor and EditorFor to create custom outputs for MVC
Upvotes: 0