简体   繁体   English

用Java编写的Razor

[英]Razor in Javascript

I don't know how to use razor syntax in Javascript. 我不知道如何在Javascript中使用剃刀语法。 I want to make Html.ListBoxFor with items from my model. 我想使用模型中的项目制作Html.ListBoxFor。 I used to use: 我曾经用过:

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

As you see I want also use chzn-select class, to have better layout. 如您所见,我还希望使用chzn-select类,以具有更好的布局。

For now, I just have this code above in HTML as plain text, but I want have there things from my model. 现在,我只是将上面的这段代码以纯文本的形式保存在HTML中,但我希望模型中包含这些内容。

Any ideas? 有任何想法吗?

There is my code in ASP.NET MVC: 我的代码在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>
}

And there is javascript file: 并且有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();

My ViewModel: ExamModel.cs: 我的ViewModel: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() in controller: 我在控制器中的ActionResult Generate():

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

While you can generate HTML in Javascript using Razor, if the Javascript is in an MVC view, I find that injecting into JS leads to maintenance problems. 虽然可以使用Razor在Javascript中生成HTML,但是如果Javascript在MVC视图中,我发现注入JS会导致维护问题。 You ideally want all your JS in separate files to allow for bundling/caching and the ability to break-point the JS code (which is harder in the view). 理想情况下,您希望将所有JS放在单独的文件中,以允许捆绑/缓存以及断点JS代码的能力(在视图中更难)。

Either inject only simple things into JS on the page, or inject elements instead. 要么仅将简单的内容注入到页面上的JS中,要么注入元素。

You can inject your template Razor list into a dummy script block, so you can extract the html from it later. 您可以将模板Razor列表注入到虚拟脚本块中,以便稍后可以从中提取html。 The type="text/template" means the browser will ignore it eg: 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>

The view page now looks like this (left out the irrelevant parts): 现在,视图页面如下所示(忽略了不相关的部分):

@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>
}

Script now looks like this (jQuery version with JS as comments): 脚本现在看起来像这样(带有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
});

Notes/tips: 备注/提示:

  • Place any JS in the page, at the bottom of the view, as it is easier to find. 将任何JS放在页面的视图底部,因为它更容易找到。 It does not matter where the @section Scripts is as the master page determines where it is injected on the final page. @section Scripts位置无关紧要,因为母版页决定了将其注入最终页的位置。
  • Always use single quotes ( ' ) in Javascript constants by default, so that nested strings can be " which are more often required than ' s. Just a good habit to get into. In fact if you had used them your code may have worked as you have added \\ escaping to the quotes which will mess up the Razor processing 默认情况下,请始终在Javascript常量中始终使用单引号( ' ),以便嵌套字符串可以是" ,这比'经常需要。这是一种很好的习惯。实际上,如果您使用过它们,您的代码就可以像您已经在引号中添加了\\转义,这会使Razor处理混乱

eg: 例如:

= '@Html.ListBoxFor(x => x.TagIdList, (MultiSelectList)ViewBag.Tags, new { @class = "chzn-select", data_placeholder = "Tags..." })';
  • If you add a @RenderSection("styles", required: false) to your master page(s) you can do the same thing for CSS as you do for scripts (ensuring all CSS is loaded in the header (for consistency). Just place them in a @section styles block. 如果将@RenderSection("styles", required: false)到母版页,则可以对CSS执行与脚本相同的操作(确保所有CSS均加载到标头中(出于一致性)。)将它们放在@section styles块中。

eg 例如

<head>
    ...
    @Styles.Render("~/Content/css")
    @RenderSection("styles", required: false)
    ...
</head>
  • ~~ is a handy (and fast) alternative to parseInt to convert values to integers. ~~parseInt的便捷(快速)替代方法,可将值转换为整数。
  • Use $ as a prefix for jQuery object variables. 使用$作为jQuery对象变量的前缀。 This makes it easier to remember when to use jQuery methods vs DOM properties. 这使您更容易记住何时使用jQuery方法和DOM属性。

Test controller code: 测试控制器代码:

    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);
    }

If it's a static JavaScript file and you are not generating it dynamically with razor view engine It won't work because in this case there is no processing performed on a server side. 如果它是静态JavaScript文件,并且您不是使用razor视图引擎动态生成的,则此文件将不起作用,因为在这种情况下,服务器端不会执行任何处理。 It is the same as accessing static html page/css file/image and etc... 它与访问静态html页面/ css文件/图像等相同。

On the other hand if this JavaScript is part of some Razor view, which means that it gets rendered by razor view engine, when you have return View() (or anything like that) in your controller action, than this code should work. 另一方面,如果此JavaScript是某些Razor视图的一部分,则意味着它由razor视图引擎呈现,当您在控制器操作中return View() (或类似的东西)时,此代码应该可以工作。

The problem is, java script files are not processed by server, so you won't be able to insert anything in those using ASP.NET MVC. 问题是,服务器无法处理Java脚本文件,因此您将无法在使用ASP.NET MVC的文件中插入任何内容。 Razor files on the other hand are processed on server so you can insert data into those (either through view bag or model). 另一方面,Razor文件在服务器上处理,因此您可以将数据插入其中(通过查看包或模型)。

One way is: 一种方法是:

.cshtml: .cshtml:

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

then use this variable in your javascript file: 然后在您的javascript文件中使用此变量:

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

The other way is to have all javascript in .cshtml file and render it as a partial view. 另一种方法是将所有javascript保存在.cshtml文件中,并将其呈现为部分视图。

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

edit: seeing your code, this will not help you very much. 编辑:看到您的代码,这对您没有太大帮助。

If you want to dynamically add/remove dom elements, you will have to do it with javascript: either generate them with "document.createElement()" or load them via ajax if you want some server side processing. 如果要动态添加/删除dom元素,则必须使用javascript:使用“ document.createElement()”生成它们,或者如果需要一些服务器端处理,则通过ajax加载它们。

@Html.ListBoxFor

is a server side helper that generates tag and fills it up depending on the parameters. 是一个服务器端帮助程序,它根据参数生成并填充标签。 You can do that with javascript as well. 您也可以使用javascript。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM