Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 3 Razor View: Generating JavaScript from a boolean model value

I am using ASP.Net MVC 3 Razor view engine.

I have a requirement to generate some JavaScript code in my View based on a value in my View Model. The value I need to use is a boolean, for this example lets call it IsSet.

So what I want to do is create a JavaScript boolean based on this value that I can use in the script later on.

Keep in mind that for all below examples I have this bit of code at the top of my view...

@{ string IsSet = Model.IsSet  ? "true" : "false"; }

NOTE: All examples below are JavaScript.

First attempt...

var IsSet = @(IsSet);

... this actually works, the problem is it breaks the auto-formatting (CTRL + E, D) in VS 2010 due to badly formatted JavaScript - as you might expect, and this is not acceptable.

Second attempt...

var IsSet = "@(IsSet)";

...I know, JavaScript is clever, it will auto-parse my string when needed. Ooops, forgot it is a string type and anything other than empty evaluates to true.

Third attempt...

var IsSet = Boolean("@(IsSet)");

....surely this will work... nope, convert non-empty string to true again (bad parser!)

Fourth attempt...

var IsSet = "@(IsSet)" === "true";

Finally something that works, but it doesn't look great to me.

I will use this if need be but ultimately my question is: Is there a better way to handle this kind of situation? Perhaps, the unwanted behaviour in my first attempt is just something that Microsoft may have overlooked?

If anybody has a nice and tidy fifth attempt for me, that would be good.

The important thing for me is that the auto-formatting in VS 2010 does not break

Thanks

like image 489
musefan Avatar asked Dec 19 '11 11:12

musefan


3 Answers

I just wrestled with the same issue for about an hour. My final solution was equivalent to the following.

var IsSet = @(Model.IsSet.ToString().ToLower()); // Inside JavaScript block

This requires no additional code.

like image 189
user1003221 Avatar answered Oct 31 '22 23:10

user1003221


None of the versions shown so far (both in the question and answers) is something that I would use. Here's how I would do it:

@model MyViewModel
<script type="text/javascript">
    var isSet = @Html.Raw(Json.Encode(Model.IsSet));

    // TODO: use the isSet javascript variable here as a standard boolean value
</script>

or if you needed other properties of your view model to be manipulated with javascript you could JSON encode the entire model:

@model MyViewModel
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));

    if (model.IsSet) {
        alert(model.FooBar);
    }
</script>
like image 11
Darin Dimitrov Avatar answered Oct 31 '22 22:10

Darin Dimitrov


Version 1 is the only one of those that I'd vote for even if they all worked, because it's the most human-readable. Unfortunately I don't have VS at home so I can't try it out to see what the auto-formatting issue is, but if at all possible I'd want to ignore the issue and go ahead and use that version given that there's nothing actually wrong with the code - it is just VS that is confused. (Are you saying VS is trying to interpret the whole thing as JS and thus finding it invalid?)

But if you want some other options:

Fifth attempt...

@{ string IsSet = Model.IsSet  ? "true" : ""; }

var isSet = !!"@(IsSet)";
// OR
var isSet = Boolean("@(IsSet)");

Coerce the string value into a boolean with the old double-not-operator trick - as you already pointed out both "true" and "false" would become true, but this problem goes away if you use "true" and "" (empty string) - so you can use Boolean() as per your "third attempt".

Sixth attempt...

@{ string IsSet = Model.IsSet  ? "true" : "false"; }

// helper function at the top of your page:
function bool(strVal) {
   return strVal === "true";
}

// variable declaration
var isSet = bool("@(IsSet)");

OK, so you end up with a fairly pointless function at the top of your page, but it keeps the actual variable declarations reasonably tidy and if debugging client side you'll see bool("false") or bool("true").

Seventh attempt...

I don't like the extra step of creating the server-side string IsSet = Model.IsSet ? "true" : "false"; in advance. I don't know Razor syntax, but can you say something along the lines of:

var isSet = !!"@(Model.IsSet ? "true" : "")";
// OR, better:
var isSet = !!"@(rzrBool(Model.IsSet))";
// where rzrBool() is a server-side helper function (that you would create)
// which returns "true" or ""

I would expect all of my "attempts" to work, but again I think your "first attempt" is the best option.

like image 7
nnnnnn Avatar answered Oct 31 '22 22:10

nnnnnn