59

I am using the default asp.net MVC 2 syntax to construct TextBox's which are integer or decimal for my asp.net MVC web app:

<%: Html.TextBoxFor(model => model.Loan.InterestRate) %>

pretty straight forward, but the problem is inherently of the fact my binding model objects are decimal or int and non-nullable, they print their value as zero (0) on page load if my model is empty (such as in add mode for a CRUD template) and zero is an incorrect value and is invalid for my page validation also.

How could I have textboxes which have no starting value, just an empty textbox, I understand zero is a potential value, but I only accept values greater than zero anyway, so this is not a problem for me.

I even tried casting as a nullable decimal and also a non-for helper (which is not ideal), but alas, I am still receiving the default '0' value. any ideas??

<%: Html.TextBox("Loan.InterestRate", Model.Loan.InterestRate == 0 ? 
    (decimal?)null : Model.Loan.InterestRate) %>
Edward Brey
  • 40,302
  • 20
  • 199
  • 253
GONeale
  • 26,302
  • 21
  • 106
  • 149

8 Answers8

66

In your model add DisplayFormat attribute

[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:#.#}")]  
decimal  InterestRate { get; set; }

View

@Html.TextBoxFor(model => model.InterestRate)

This outputs empty instead of 0. More format examples here

Update

TextBoxFor does`s not works with format, but EditorFor does:

@Html.EditorFor(model => model.InterestRate)

Update 2

It does work for TextBoxFor this way:

@Html.TextBoxFor(model => model.InterestRate, "{0:#.#}")
Agat
  • 4,577
  • 2
  • 34
  • 62
Sel
  • 1,934
  • 1
  • 22
  • 13
  • 9
    I like this the best, leverage the existing technologies the way they are meant to be used. All the others use some kind of hack in the view or ternary operators or client side checks. This is clean and provides other good examples. – akousmata Nov 05 '14 at 17:56
  • 1
    This didn't work for me. Did it work for anybody else? – JoshYates1980 Jun 16 '15 at 16:14
  • Try use Html.EditorFor instead of Html.TextBoxFor – Sel Jun 17 '15 at 06:15
49

I use this solution :

   @Html.TextBoxFor(model => model.Year, new { Value = "" })

refer to : https://stackoverflow.com/a/6186576/297487

Community
  • 1
  • 1
Khosro
  • 707
  • 1
  • 7
  • 16
  • 14
    It should be noted that this doesn't work well when used with typical MVC server-side validation where you redisplay the view with the validation errors (Ex; `if(!ModelState.IsValid) return View(viewmodel)`). Anytime the textbox is rendered at page load, it's going to display an empty string. This is great for regular first-time rendering of the page, but bad when the user is coming back due to validation failing. Whatever data they entered in the fields will be lost and replaced with the empty string. – EF0 May 16 '14 at 21:17
  • 5
    @EFO then you can use `Value = (Model.Loan.InterestRate > 0 ? Model.Loan.InterestRate.ToString() : "")` – devqon Aug 19 '15 at 11:15
16

You can override the default template by putting a custom template in /Shared/EditorTemplates or by controller in /ControllerName/EditorTemplates.

I use this one for Int's. Its named Int32.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="System.Web.Mvc.Html" %>
<%
    string displayText = string.Empty;

    if (Model != null)
    {
        displayText = Model.ToString();
    }

%>

<%= Html.TextBox("", displayText)%>
John Farrell
  • 24,673
  • 10
  • 77
  • 110
  • 7
    not sure why this is the accepted answer as it will always display the value of the integer, the Model is a (not nullable) int – politus Jan 15 '13 at 11:36
11

Another one could be to check the value

@Html.TextBoxFor
(m => m.CertificateID, new { @Value = (Model.CertificateID > 0 ?Model.CertificateID.ToString() :string.Empty) })
Baby Groot
  • 4,637
  • 39
  • 52
  • 71
Sandeep
  • 615
  • 6
  • 13
  • 1
    This causes the tag to have two values in the HTML it's behavior might change on future browsers – Jeff Sep 23 '13 at 05:10
4

An alternative solution is to use jQuery to replace zeros with empty string when the page loads. Choose any name to use as a class name for all input fields which should be populated with empty string instead of zero. For example non-zero-num.

@Html.TextBoxFor(model => model.InterestRate, new { @class = "non-zero-num" }) 

And add the following script on your page:

<script>
    $(document).ready(function(){
        $(".non-zero-num").val($(this).val() == 0 ? '' : $(this).val());
    })
</script>
Majix
  • 570
  • 7
  • 14
  • 2
    And for those users without javascript enabled? It is best to only add visual improvements with javascript. – Samuel Parkinson Sep 25 '12 at 15:33
  • 2
    Hi Sam. Javascript is now considered not only a means of visual improvements to the UI, but also in many (and I can say in most of the modern web-based) applications, it is used to implement the business logic. Just to name a few, Google applications such as maps, docs, and gmail are among them. – Majix Dec 01 '12 at 21:07
  • It is very interesting that [Jeff Atwood](http://en.wikipedia.org/wiki/Jeff_Atwood), one of the co-founders of this very website, stackoverflow, has proposed something along this line. I'm quoting from Wikipedia: "He is also credited with the proposal of Atwood's Law which is a corollary to the Rule of least power design principle. It states that any application that can be written in JavaScript will eventually be written in JavaScript." – Majix Dec 01 '12 at 21:29
  • 1
    While I do agree Javascript for some sites is a valid requirement, for something like this that can be somewhat trivially solved with server side code you might as well. – Samuel Parkinson Dec 04 '12 at 09:48
4

What about "" instead of null.

    <%: Html.TextBox("Loan.InterestRate", 
Model.Loan.InterestRate == 0 ?     "" : Model.Loan.InterestRate) %>

Also why isnt Loan.InterestRate nullable?

<%: Html.TextBox("Loan.InterestRate", Model.Loan.InterestRate ?? "") %>
bleevo
  • 1,637
  • 2
  • 18
  • 30
0

I think @jfar's answer points in the right direction but the Int32.ascx should be this

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Int32>" %>
<%
    string displayText;

    if (Model == 0)
    {
        displayText = "";
    }
    else
    {
        displayText = Model.ToString();
    }

%>  

<%= Html.TextBox("", displayText)%>

or updated answer using Razor (/Shared/EditorTemplates/Int32.cshtml)

@model Int32
@{
    string text = Model == 0 ? "" : Model.ToString();
}
@Html.TextBox("", text)
politus
  • 5,996
  • 1
  • 33
  • 42
0

Here is what you can do: (VB Code)

This is the core:

@IIf(Model.YourNumericValue = 0, "", Model.YourNumericValue)

Here is if you use the HTML to render your textbox

<input type="text" name="sYourTextboxName"  value="@IIf(Model.YourNumericValue= 0, "", Model.YourNumericValue))">

Here is if you use HTML helper to render you textbox

 @Html.TextBox("sYourTextboxName", IIf(Model.YourNumericValue= 0, "", Model.YourNumericValue))

IIf is a very handy one line feature - the way it works is this.

IIf(Expression, TruePart, FalsePart)

So basically you saying - if my Parameter = 0 - I want to output nothing, String.Empty, Null, "" - and for the false part - it is like - oh if my Parameter does not equal to 0 - then that must be something other than 0 - so I will output the my numeric value without worrying that the zero will be in the textbox.

Or however you want to structure it.

Hope that helped!

Alexey Shevelyov
  • 926
  • 1
  • 13
  • 24