Whirlwind991
Whirlwind991

Reputation: 495

Embedding Razor within HTML within JS

I have a dynamic table generated in JS which appends a button (and image) in one of the columns of the table:

var btn = $("<button/>", { class: "btn btn-default dropdown-toggle options_btn_custom", }).prepend('<img src="@Url.Content("~/Content/img/Settings.png")" />');

The issue is the Razor image URL within the HTML is rendered incorrectly:

enter image description here

The URL of the image has to be relative (hence the Razor)...

I know its possible to embed Razor within JS directly, but is there a way for it to work also within embedded HTML, or is it too far a long shot?

Upvotes: 0

Views: 99

Answers (4)

Marlon Navas
Marlon Navas

Reputation: 141

You could render a data attribute to a container holding the objects you will generate dynamically. Doing so prevents the usage of global javascript variables.

<div id="myAwesomeFunctionalityContainer" data-image-url="@Url.Content("~/Content/img/")"></div>

Then from your javascript file, read the data attribute "image-url"

(function () {
   "use strict";

   $(window).load(function () {
      var $container = $("#myAwesomeFunctionalityContainer");
      var imgPath = $container.data("image-url");
      var classDef = "btn btn-default dropdown-toggle options_btn_custom";
      var btn = $("<button/>", {class: classDef}).prepend('<img src="' + imgPath + '/Setting.png" />');
   });
}());

The benefits are:

  • no global variables which will cause headaches if you code libray grows.
  • the payload is known to the container using data attributes. This works well for a limited amount of data. If you need more data/complex object from razor then you could render a model to a json string object. Afterwards convert the string object back to a json object using jquery.parseJSON

Upvotes: 0

Sergey Metlov
Sergey Metlov

Reputation: 26341

The fact is Razor is not configured to process JS files by default. The easiest solution will be to inject your values in cshtml file in the script tag before your JS file reference:

<script>
    window.data = {
        settingsImageUrl: '@Url.Content("~/Content/img/Settings.png")';
    };
<script>
<script src="your-script.js" />

And then feel free to use data.settingsImageUrl in your-script.js:

var btn = $("<button/>", {
    class: "btn btn-default dropdown-toggle options_btn_custom", 
}).prepend('<img src=" + data.settingsImageUrl + " />');

Alternative solution

Another possible solution is to build the script file with all the values required for your script on the fly. To make this you can setup a special route pointing to an action. In this action you will build your values as a string with JS object definition and return it as a text/javascript content. That will work fine with caching action filter. Then you just point to this route in a script tag injected before your target script.

Upvotes: 0

RAHUL S R
RAHUL S R

Reputation: 1579

you can set the value to a global js var and then you can use it in external js file

i.e

> var clientVar = null;
> 
> clientVar = '@Url.Content("~/Content/img/Settings.png")';

in external js file just use the clienVar. it should work

Upvotes: 0

Whirlwind991
Whirlwind991

Reputation: 495

Quick fix, didn't know I had to keep the Razor within the view... so in my view head I've got:

    <script>
    var baseurl = "@Url.Content("~/")";
    </script>

And then the JS within the external file:

 var btn = $("<button/>", { class: "btn btn-default dropdown-toggle options_btn_custom" }).prepend('<img src="' + baseurl + '/Content/img/Settings.png"/>');

Upvotes: 1

Related Questions