Razor in Javascript

Razor in Javascript

本文关键字:Javascript in Razor      更新时间:2023-09-26

我不知道如何在Javascript中使用剃刀语法。我想用我的模型中的项目制作Html.ListBoxFor。我以前用过:

@Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { @class = "chzn-select", data_placeholder = "Tags..." })

正如你所看到的,我还想使用chzn-select类,以获得更好的布局。

目前,我只是将上面的HTML代码作为纯文本,但我希望从我的模型中获得这些东西。

有什么想法吗?

ASP.NET MVC中有我的代码:

@model Generator.Models.ExamModel
@{
    ViewBag.Title = "Generate";
}
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script src="@Url.Content("~/Multiple_chosen/chosen.jquery.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/ListOfTags.js")" type="text/javascript"></script>
    <script >    
        $(".chzn-select").chosen();
    </script>
}
<link href="@Url.Content("~/Multiple_chosen/chosen.css")" rel="stylesheet" type="text/css" />
<h1>@ViewBag.Title</h1>
<h2>@ViewBag.Message</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Generate</legend>

        <div class="editor-label">Numbers</div>
        <div class="editor-field" id="NumberOfModels">
            @Html.EditorFor(model => model.NumberOfQuestions)
        </div>
        <div class="editor-label">Tags</div>
        <div id="itemsmodel"></div>
        <br>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

还有一个javascript文件:

var models = document.getElementById("NumberOfQuestions");
var modelsTable = document.getElementById("itemsmodel");
models.addEventListener("change", drawModels, false);
function drawModels() {
    var modelsNum = parseInt(models.value);
    var curModels = modelsTable.childElementCount;
    if (modelsNum > curModels) {
        var delta = modelsNum - curModels;
        for (var i = 0; i < delta; i++) {
            var input = document.createElement("div");
            input.className = "editor-field";
            input.innerHTML = "@Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { @class = '"chzn-select'", data_placeholder = '"Tags...'" })";
            modelsTable.appendChild(input);
        }
    } else {
        while (modelsTable.childElementCount > modelsNum) {
            modelsTable.removeChild(modelsTable.lastChild);
        }
    }
}
drawModels();

我的视图模型:ExamModel.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ExamGenerator.Models
{
    public class ExaminationModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<int> TagIdList { get; set; }
        public int NumberOfQuestions { get; set; }
        public string Content { get; set; }
    }
}

控制器中的My ActionResult Generate():

public ActionResult Generate()
{
    ViewBag.Tags = new MultiSelectList(genKolEnt.TAGS, "Id", "Name", null); 
    return View();
}

虽然您可以使用Razor在Javascript中生成HTML,但如果Javascript处于MVC视图中,我发现注入JS会导致维护问题。理想情况下,您希望所有JS都在单独的文件中,以便进行绑定/缓存,并能够中断JS代码(这在视图中更难)。

要么只向页面上的JS注入简单的东西,要么注入元素。

您可以将模板Razor列表注入到一个伪脚本块中,以便稍后从中提取html。type="text/template"表示浏览器将忽略它,例如:

<script id="ListTemplate" type="text/template">
    @Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { @class = "chzn-select", data_placeholder = "Tags..." })
</script>

视图页面现在看起来是这样的(去掉了不相关的部分):

@section styles{
    <link href="@Url.Content("~/Multiple_chosen/chosen.css")" rel="stylesheet" type="text/css" />
}
<h1>@ViewBag.Title</h1>
<h2>@ViewBag.Message</h2>
<script id="ListTemplate" type="text/template">
    @Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { @class = "chzn-select", data_placeholder = "Tags..." })
</script>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Generate</legend>

        <div class="editor-label">Numbers</div>
        <div class="editor-field" id="NumberOfModels">
            @Html.EditorFor(model => model.NumberOfQuestions)
        </div>
        <div class="editor-label">Tags</div>
        <div id="itemsmodel"></div>
        <br>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

脚本现在看起来是这样的(带有JS作为注释的jQuery版本):

// ListOfTags.js file
// This is a shortcut DOM ready handler for $(document).ready(function(){ YOUR CODE HERE })
$(function () {
    // Attach an event handler for the "change" event
    $('#NumberOfQuestions').change(function () {
        var $numberOfQuestions = $(this);                       // Convert current DOM element (the counter) to a jQuery element
        var $modelsTable = $('#itemsmodel');                    // document.getElementById("itemsmodel");
        var modelsNum = ~~$numberOfQuestions.val();             // parseInt(models.value);
        var curModels = $modelsTable.children().length;         // modelsTable.childElementCount
        var delta = modelsNum - curModels;
        // While too few, add more
        while (delta > 0) {
            var $input = $('<div>').addClass('editor-field');   // document.createElement("div"); .className = "editor-field";
            var template = $('#ListTemplate').html();           // Fetch the template from a script block (id="ListTemplate")
            $input.html(template);                              // input.innerHTML = 
            $modelsTable.append($input);                        // modelsTable.appendChild(input);
            delta--;
        }
        // While too many, remove the last
        while (delta++ < 0) {
            $modelsTable.children().last().remove();            // modelsTable.removeChild(modelsTable.lastChild);
        }
    }).change();        // Trigger an initial change event so it runs immediately
});

注意事项/提示:

  • 将任何JS放在页面中的视图底部,这样更容易找到。@section Scripts在哪里并不重要,因为母版页决定了它在最终页面上的注入位置
  • 默认情况下,总是在Javascript常量中使用单引号('),这样嵌套字符串就可以是",这比'更经常需要。这是一个很好的习惯。事实上,如果你使用了它们,你的代码可能已经工作了,因为你在引号中添加了'转义,这会扰乱Razor的处理

例如:

= '@Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { @class = "chzn-select", data_placeholder = "Tags..." })';
  • 如果将@RenderSection("styles", required: false)添加到母版页,则可以对CSS执行与对脚本执行相同的操作(确保所有CSS都加载在页眉中(以保持一致性)。只需将它们放在@section styles块中即可

例如

<head>
    ...
    @Styles.Render("~/Content/css")
    @RenderSection("styles", required: false)
    ...
</head>
  • ~~是将值转换为整数的parseInt的方便(快速)替代方案
  • 使用$作为jQuery对象变量的前缀。这样可以更容易地记住何时使用jQuery方法与DOM属性

测试控制器代码:

    private MultiSelectList TagList()
    {
        var items = new List<KeyValuePair<int, string>>() { 
            new KeyValuePair<int, string>(1, "MVC"), 
            new KeyValuePair<int, string>(2, "jQuery"), 
            new KeyValuePair<int, string>(3, "JS"), 
            new KeyValuePair<int, string>(4, "C#"), 
            new KeyValuePair<int, string>(5, "PHP")
        };
        MultiSelectList list = new MultiSelectList(items, "key", "value", null);
        return list;
    }
    // Get request starts with one list
    public ActionResult Test()
    {
        ExamModel vm = new ExamModel()
        {
            NumberOfQuestions = 1,
            TagIdList = new List<int>()
        };
        ViewBag.Tags = TagList();
        return View(vm);
    }
    [HttpPost]
    public ActionResult Test(ExamModel model)
    {
        ViewBag.Tags = TagList();
        return View(model);
    }

如果它是一个静态JavaScript文件,并且您没有使用剃刀视图引擎动态生成它它将不起作用,因为在这种情况下,服务器端没有执行任何处理。它与访问静态html页面/css文件/image等相同…

另一方面,如果这个JavaScript是某个Razor视图的一部分,也就是说,当你的控制器操作中有return View()(或类似的东西)时,它会被Razor查看引擎渲染,那么这个代码应该可以工作。

问题是,java脚本文件不是由服务器处理的,因此您将无法在那些使用ASP.NET MVC的文件中插入任何内容。另一方面,Razor文件是在服务器上处理的,所以您可以将数据插入其中(通过视图包或模型)。

一种方法是:

.cshtml:

<script>
    var someVariable = '@model.data';    
</script>

然后在javascript文件中使用这个变量:

function someFunction(){
  var myData = window.someVariable;
}

另一种方法是将所有javascript都放在.cs.html文件中,并将其呈现为部分视图。

@Html.Partial("Path/to/javascript/in/razor/view")

编辑:看到你的代码,这对你没有多大帮助。

如果你想动态添加/删除dom元素,你必须使用javascript:要么用"document.createElement()"生成它们,要么如果你想进行一些服务器端处理,就通过ajax加载它们。

@Html.ListBoxFor

是一个服务器端助手,它生成标签并根据参数填充标签。您也可以使用javascript来实现这一点。