0

This is the declaration I am trying to place within a variable

var levelDropdown = "@Html.DropDownListFor(m => m.Level, Model.Levels, null, null)";
var level = "<div class='col-sm-3 search-spacing'><label for='Level'>Level</label>" + levelDropdown +"</select></div>";

However, when I run it, I get an invalid identifier error. When I remove these 2 lines, the page loads again. Is there a way to place razor syntax into a javascript variable or how can I convert this to normal html syntax instead?

JianYA
  • 2,750
  • 8
  • 60
  • 136
  • 1
    You have additional `` closing tag which should be removed. Also using `DropDownListFor` assignment for JS variable is not considered a good way, why not just render it on CSHTML page directly? – Tetsuya Yamamoto Oct 30 '18 at 02:00
  • I'll try to render them on cshtml first then. I didn't think to do that earlier. – JianYA Oct 30 '18 at 02:02
  • Check the view source of the page and you will understand what is breaking (multi line without proper closing bracket) – Shyju Oct 30 '18 at 02:03

1 Answers1

1

Your definition of DropDownListFor for levelDropdown is not work because it creates line breaks between <select> and <option> tags, as shown in result below:

var levelDropdown = "<select id="Level" name="Level"><option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
<option value="4">Option 4</option>
</select>";

The code above is not a valid JS, hence Unexpected identifier error occurred.

To fix this problem, use Ajax.JavaScriptStringEncode() method together with ToHtmlString() to generate correct HTML:

var levelDropdown = '@Ajax.JavaScriptStringEncode(Html.DropDownListFor(m => m.Level, Model.Levels, null, null).ToHtmlString())';

Then strip out all line breaks inside levelDropdown by using String.replace() on JS:

var level = "<div class='col-sm-3 search-spacing'><label for='Level'>Level</label>" + 
             levelDropdown.replace(/(\r\n\t|\n|\r\t)/gm,"") +"</div>";

Finally use append() to add the dropdown into target element:

$('#targetElement').append(level);

Note: The solution above only applies for MVC 5 (see fiddle). If Core MVC is used, there's no Ajax.JavaScriptStringEncode() and ToHtmlString() methods for string conversion against DropDownListFor, hence create your own ToHtmlString() method with helper class and System.Text.Encodings.Web.JavaScriptEncoder to encode the output:

Helper class

public static string ToHtmlString(this IHtmlContent htmlContent)
{
    using (var writer = new StringWriter())
    {
        htmlContent.WriteTo(writer, System.Text.Encodings.Web.HtmlEncoder.Default);
        return writer.ToString();
    }
}

View

@{
    // include the helper class 
    var ddlf = System.Text.Encodings.Web.JavaScriptEncoder.Default.Encode(Html.DropDownListFor(m => m.Level, Model.Levels, null, null).ToHtmlString());
}
<script>
    var levelDropdown = '@ddlf';
    var level = "<div class='col-sm-3 search-spacing'><label for='Level'>Level</label>" + 
                levelDropdown.replace(/(\r\n\t|\n|\r\t)/gm,"") +"</div>";
    $('#targetElement').append(level);
</script>

Related issue:

Using Html.dropdownList() in Javascript Code

Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61