Skip to content

No value rendered for zero (0) numbers #31

skenny opened this Issue Dec 2, 2011 · 20 comments

6 participants

skenny commented Dec 2, 2011

JSON number values that are 0 are not rendered. For example:


Quantity: {{=quantity}}



Yes, thanks, I was aware of this issue, and will fix it soon...

ghost commented Dec 8, 2011

I have same problem any luck with this issue?
Right now I can only use the code like: {{=$itemNumber-1 undef 0}}


I'm planning to include a fix for this, but it may have to wait until some bigger changes that are in the pipeline, since it relates to other issues like #7 - and to make both that issue and this one satisfied has to be compatible with maintaining current perf optimization. If you have a workaround, then best to stay with that in the meantime...

Davepar commented Dec 13, 2011

+1, but workaround does work

Arakade commented Dec 21, 2011

+1 but couldn't get workaround to work with an encoder (new workaround using a function below).

Pre-workaround, I started with {{=shopping.change.amount!currency}} where "currency" is a custom formatter (encoder) registered with...

  $.views.encoders["currency"] = function currency(number) {
    //alert("typeof "+ number +": "+ typeof number);
    try {
      return number.toFixed(2);
    } catch(e) {
      // supplied something other than a number
      return number +"(NaN)";

... so my unformatted workaround became {{=shopping.change.amount undef 0}} which works but has no formatting.
I then tried adding the encoder as {{=shopping.change.amount undef 0!currency}} but it gave same results as no workaround (value if non-zero; else blank).

I then went and read the source but can't adequately-grok-in-sensible-time how to use a formatter with the workaround (thattmpl + compile code is kind'a heavy! :-O ). Guessing didn't work either ;-)

In case it's relevant, I'm using this with JQuery loaded.

Alternative workaround (that allows formatting)

Instead, I switched to using a function...

    currency: function(number) {
      // alert("typeof "+ number +": "+ typeof number);
      try {
        return number.toFixed(2);
      } catch(e) {
        // supplied something other than a number
        return number +"(NaN)";

... and my template obviously now has {{=$ctx.currency(shopping.change.amount)}}.
Zero and all other values render correctly. HTH other zero formatters!


$.template("Quantity: {{=quantity}}")
generates ... result = "" + "Quantity: " + html($data.quantity || "");
where it should be ... result = "" + "Quantity: " + html($data.quantity);
and $.views.encoders.html should become:

function (text) { 
   if (null == text) return ""; // skip null and undefined elements.
   return String(text).replace(htmlSpecialChar, replacerForHtml); 

(null == text) is true for undefined and null elements, but false for 0 and false,
whereas (text || "") will evaluate to "" for null, undefined, false, and 0.

Another inline optimization possibility is (null == text ? "" : text) instead of (text || "")
which should have good performance and certainly shorter than
("undefined" === typeof text || null === text ? "" : text).


Looks like this problem comes from the paramsOrEmptyString optimization.

I have branch ( with a commit (josher19/jsviews@338755b) which gets rid of the optimization and puts a similar one in the html encoder. HTML encoded text using {{= item }} will return blank ('') for undefined or null values but not for 0 or false, but using the ! will show 'undefined' and 'null' values:
{{= item !}}

Example usage:

$.template("HTML", "
Qty: {{=Qty}}, null:{{=nil}}, notset:{{=blank}}, bool:{{=bool}}
")(falsy={"Qty":0,"nil":null,"bool":false}) // Expected output:
Qty: 0, null:, notset:, bool:false
// Old output:
Qty:, null:, undefined:, bool:
$.template("NONE", "
Qty: {{=Qty!}}, null:{{=nil!}}, notset:{{=blank!}}, bool:{{=bool!}}
")(falsy={"Qty":0,"nil":null,"bool":false}) // Expected output:
Qty: 0, null:null, notset:undefined, bool:false
// Old output:
Qty:, null:, notset:, bool:

Seeing this open for a year doesn't give me hope I could offer a fix myself, so I hate to simply post a breaking example in both the current jsrender and @josher19's version. I'm still going to take a look at the jsrender source when I get the chance, but there is definitely still an issue when $data is 0. Here's the gist of the example:

<ul id="results"></ul>
<script id="x" type="text/x-jquery-tmpl">
<script type='text/javascript'>
    $("#results").html($("#x").render([0, 1, 0, 2, 0]));

Results in: "<ul id="results"><li>1</li><li>2</li></ul>"

It doesn't even appear to attempt to step into the template to render the zero-value elements of that array. This seems to make workarounds like the custom tag, custom encoder, and helper function ideas fail too.


! do have a fix for this already, but it is part of a major update which I have not committed because it involves some breaking changes. I don't want to do breaking changes piecemeal - but rather in one significant upgrade which will require some porting to the new syntax. After that I hope to keep things pretty stable. The JsRender update is ready, but it also ripples to some changes in JsViews, and I am working hard now to integrate JsViews changess with this update too.

So apologies that this is taking some time, but I think/hope the update will be worth the wait! It should be committed in a couple weeks time... I am targetting Beta for JsRender end of February...


@patridge : fixed in my fork of the code so now your results render correctly with 0's included in the output.

Technical details: changed render to do

content = null != dataItem ? tmpl( dataItem, new View( context, path, arrayView, dataItem, tmpl, this )) : "";

instead of

content = dataItem ? tmpl( dataItem, new View( context, path, arrayView, dataItem, tmpl, this )) : "";

so now it will render the template for each line unless that line is null or undefined
(before it would skip rendering if the dataItem was falsy, meaning 0, false, "", null, or undefined).

Thanks for posting the example. It indirectly makes a strong argument for TDD.

@BorisMoore: feel free to pull these small changes and merge them with your changes to see if it fixes or breaks anything. Also let me know if you would like help setting up a test suite for new JsRender beta.

PS: Now 0 and false will show up whether or not you use ! when rendering:

$.template('qq', 'Quantity: {{=quantity!}}, Boolean: {{=bool!}}')({quantity:0, bool:false})
// "Quantity: 0, Boolean: false"

$.template('qq', 'Quantity: {{=quantity}}, Boolean: {{=bool}}')({quantity:0, bool:false})
// "Quantity: 0, Boolean: false"

I forked your " breaking example" JsFiddle and added a couple more tests.

Red (failing):

Green (passing):


Hi Boris,

Updated the original example to use your new code:

<ul id="results"></ul>
<script id="x" type="text/x-jquery-tmpl">
    <li>{{: #data }}</li>
/*global $ */
$(function() {
    "use strict";
    $("#results").html($("#x").render([-1, 0, 1, 2, 3, 4,
                                  '-- booleans --',
                                  false, true,
                                  '-- null & undefined --',
                                  null, undefined,
                                  '-- strings --',
                                  "", "string"]));

Now get '[object Object]' for the "falsy" values of 0, "", null, undefined, and false.

->> Josh <<-


Ah, I see. Yes that is a slightly different case than the one I was looking at. I was thinking of the case where you have a data object with a property whose value is 0, or undefined. (e.g. { quantity: 0 } as above) - but this additional scenario is valid too. I have a fix for it, which I'll upload soon...


Fixed in 5d284cb.
Closing, but please reopen if the fix does not work for you... Thanks...

@BorisMoore BorisMoore closed this Mar 11, 2012

Yes, that seems to work pretty well:

Now undefined is replaced with "" (a blank string) and null is replaced with the String "null", while 0 and false remain unchanged.


Yes, that's the intention. Actually, undefined, 0, null, true and false are rendered by the strings "", "0", "null", "true", "false". Would you expect anything different from this design?

JsRender always renders a string, of course. The return value from render() can never be other than a string.


No, I think "" for undefined and "null" for null works well -- issue closed!

You might include in the documentation how to change that back to the old way (delete "falsy" values) or how to change "null" to "" using a helper function.


There has been a new issue submitted suggesting null should render as "".
I think it does make more sense. Any disagreement?


I agree. Might include in the docs how to customize what is displayed using helper functions, because displaying "null" can be useful for debugging, but not so useful for displaying in final HTML produced by render.


This definitely fixed that sample jsFiddle (once I updated the syntax: original). I would think an empty string for null/undefined ought to be just fine. I have only had one use-case where I wanted to display "null" for null values and that was an oddball usage. I put together the start of a simple demo using a helper function to display such values for anyone else that runs into a need to do so; it's not elegant, but it should be easily tweaked for someone's debugging needs.

@ashok-conflux ashok-conflux referenced this issue in openMF/mifosx-community-apps Feb 10, 2013

MIFOSX-36- Add/Edit Code value UI changes #71

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.