Внедрение содержимого в определенные разделы из частичного представления ASP.NET MVC 3 с помощью Razor View Engine - PullRequest
304 голосов
/ 26 сентября 2011

У меня есть этот раздел, определенный в моем _Layout.cshtml

@RenderSection("Scripts", false)

Я могу легко использовать его из вида:

@section Scripts { 
    @*Stuff comes here*@
}

То, с чем я борюсь, это как получитьНекоторое содержимое вставлено в этот раздел из частичного представления.

Давайте предположим, что это моя страница просмотра:

@section Scripts { 

    <script>
        //code comes here
    </script>
}

<div>
    poo bar poo
</div>

<div>
  @Html.Partial("_myPartial")
</div>

Мне нужно вставить некоторое содержимое в раздел Scripts из _myPartialчастичный вид.

Как я могу это сделать?

Ответы [ 22 ]

1 голос
/ 14 августа 2014

Существует способ вставки разделов в частичные представления, хотя это не очень красиво. Вам нужно иметь доступ к двум переменным из родительского представления. Поскольку частью вашего частичного представления является создание этого раздела, имеет смысл требовать эти переменные.

Вот как выглядит вставка раздела в частичном представлении:

@model KeyValuePair<WebPageBase, HtmlHelper>
@{
    Model.Key.DefineSection("SectionNameGoesHere", () =>
    {
        Model.Value.ViewContext.Writer.Write("Test");
    });
}

А на странице вставляем частичный вид ...

@Html.Partial(new KeyValuePair<WebPageBase, HtmlHelper>(this, Html))

Вы также можете использовать эту технику для программного определения содержимого раздела в любом классе.

Наслаждайтесь!

1 голос
/ 17 августа 2018

Цель ОП заключается в том, что он хочет определить встроенные сценарии в своем частичном представлении, которое, как я предполагаю, является специфическим только для этого частичного представления, и включить этот блок в раздел сценариев.

Я понял, что он хочет, чтобы этот Частичный Взгляд был самодостаточным. Идея аналогична компонентам при использовании Angular.

Мой способ состоял бы в том, чтобы просто сохранить сценарии в Частичном представлении как есть. Теперь проблема заключается в том, что при вызове Partial View он может выполнить сценарий там раньше всех других сценариев (который обычно добавляется внизу страницы макета). В этом случае у вас есть только скрипт Partial View, ожидающий другие скрипты. Есть несколько способов сделать это. Самый простой, который я использовал ранее, это использование события в body.

На моем макете у меня было бы что-то внизу, как это:

// global scripts
<script src="js/jquery.min.js"></script>
// view scripts
@RenderSection("scripts", false)
// then finally trigger partial view scripts
<script>
  (function(){
    document.querySelector('body').dispatchEvent(new Event('scriptsLoaded'));
  })();
</script>

Тогда на моем частичном виде (внизу):

<script>
  (function(){
    document.querySelector('body').addEventListener('scriptsLoaded', function() {

      // .. do your thing here

    });
  })();
</script>

Другое решение заключается в использовании стека для передачи всех ваших скриптов и вызова каждого из них в конце. Другим решением, как уже упоминалось, является шаблон RequireJS / AMD, который также очень хорошо работает.

1 голос
/ 12 января 2017

Это сработало для меня, позволив мне совмещать javascript и html для частичного просмотра в одном и том же файле. Помогает в мыслительном процессе видеть html и связанную часть в одном файле частичного представления.


В представлении, которое использует частичное представление, называемое "_MyPartialView.cshtml"

<div>
    @Html.Partial("_MyPartialView",< model for partial view>,
            new ViewDataDictionary { { "Region", "HTMLSection" } } })
</div>

@section scripts{

    @Html.Partial("_MyPartialView",<model for partial view>, 
                  new ViewDataDictionary { { "Region", "ScriptSection" } })

 }

В режиме частичного просмотра

@model SomeType

@{
    var region = ViewData["Region"] as string;
}

@if (region == "HTMLSection")
{


}

@if (region == "ScriptSection")
{
        <script type="text/javascript">
    </script">
}
0 голосов
/ 28 января 2015

Я решил это совершенно другим путем (потому что я спешил и не хотел реализовывать новый HtmlHelper):

Я обернул свое Частичное представление в большой оператор if-else:

@if ((bool)ViewData["ShouldRenderScripts"] == true){
// Scripts
}else{
// Html
}

Затем я дважды вызвал Partial с пользовательскими данными ViewData:

@Html.Partial("MyPartialView", Model, 
    new ViewDataDictionary { { "ShouldRenderScripts", false } })

@section scripts{
    @Html.Partial("MyPartialView", Model, 
        new ViewDataDictionary { { "ShouldRenderScripts", true } })
}
0 голосов
/ 05 июня 2018

Я только что добавил этот код на свое частичное представление и решил проблему, хотя и не очень чисто, она работает. Вы должны убедиться, что идентификаторы объектов, которые вы визуализируете.

$ (документ) .ready (function () { $ ("# Profile_ProfileID"). Selectmenu ({icons: {button: 'ui-icon-circle-arrow-s'}}); $ ("# TitleID_FK"). Selectmenu ({icons: {button: 'ui-icon-circle-arrow-s'}}); $ ("# CityID_FK"). Selectmenu ({icons: {button: 'ui-icon-circle-arrow-s'}}); $ ("# GenderID_FK"). Selectmenu ({icons: {button: 'ui-icon-circle-arrow-s'}}); $ ("# PackageID_FK"). Selectmenu ({icons: {button: 'ui-icon-circle-arrow-s'}}); });
0 голосов
/ 14 декабря 2017

Используя Mvc Core, вы можете создать аккуратный TagHelper scripts, как показано ниже. Это может быть легко преобразовано в тег section, где вы также даете ему имя (или имя берется из производного типа). Обратите внимание, что внедрение зависимости должно быть настроено для IHttpContextAccessor.

При добавлении сценариев (например, в части)

<scripts>
    <script type="text/javascript">
        //anything here
    </script>
</scripts>

При выводе сценариев (например, в файле макета)

<scripts render="true"></scripts>

Код

public class ScriptsTagHelper : TagHelper
    {
        private static readonly object ITEMSKEY = new Object();

        private IDictionary<object, object> _items => _httpContextAccessor?.HttpContext?.Items;

        private IHttpContextAccessor _httpContextAccessor;

        public ScriptsTagHelper(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var attribute = (TagHelperAttribute)null;
            context.AllAttributes.TryGetAttribute("render",out attribute);

            var render = false;

            if(attribute != null)
            {
                render = Convert.ToBoolean(attribute.Value.ToString());
            }

            if (render)
            {
                if (_items.ContainsKey(ITEMSKEY))
                {
                    var scripts = _items[ITEMSKEY] as List<HtmlString>;

                    var content = String.Concat(scripts);

                    output.Content.SetHtmlContent(content);
                }
            }
            else
            {
                List<HtmlString> list = null;

                if (!_items.ContainsKey(ITEMSKEY))
                {
                    list = new List<HtmlString>();
                    _items[ITEMSKEY] = list;
                }

                list = _items[ITEMSKEY] as List<HtmlString>;

                var content = await output.GetChildContentAsync();

                list.Add(new HtmlString(content.GetContent()));
            }
        }
    }
0 голосов
/ 23 декабря 2016

Идея Плутона в лучшем виде:

CustomWebViewPage.cs:

    public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel> {

    public IHtmlString PartialWithScripts(string partialViewName, object model) {
        return Html.Partial(partialViewName: partialViewName, model: model, viewData: new ViewDataDictionary { ["view"] = this, ["html"] = Html });
    }

    public void RenderScriptsInBasePage(HelperResult scripts) {
        var parentView = ViewBag.view as WebPageBase;
        var parentHtml = ViewBag.html as HtmlHelper;
        parentView.DefineSection("scripts", () => {
            parentHtml.ViewContext.Writer.Write(scripts.ToHtmlString());
        });
    }
}

Просмотров \ web.config:

<pages pageBaseType="Web.Helpers.CustomWebViewPage">

Вид:

@PartialWithScripts("_BackendSearchForm")

Частично (_BackendSearchForm.cshtml):

@{ RenderScriptsInBasePage(scripts()); }

@helper scripts() {
<script>
    //code will be rendered in a "scripts" section of the Layout page
</script>
}

Макет страницы:

@RenderSection("scripts", required: false)
0 голосов
/ 06 декабря 2016

по выбору, вы можете использовать вашу папку / index.cshtml в качестве главной страницы, а затем добавить сценарии раздела.Затем в макете у вас есть:

@RenderSection("scripts", required: false) 

и ваш index.cshtml:

@section scripts{
     @Scripts.Render("~/Scripts/file.js")
}

, и он будет работать над всеми вашими частичными видами.Это работает для меня

0 голосов
/ 27 июля 2016

Что ж, я полагаю, что другие авторы предоставили вам средство для непосредственного включения @section в ваш фрагмент (с помощью сторонних html-помощников).

Но я считаю, что, если ваш сценарий тесно связан с вашим частичным, просто поместите ваш javascript прямо внутри встроенного тега <script> в вашем частичном и покончите с этим (просто будьте осторожны с дублирование скрипта, если вы собираетесь использовать частичное более одного раза в одном представлении);

0 голосов
/ 01 июня 2016

У меня была похожая проблема, где у меня была главная страница следующим образом:

@section Scripts {
<script>
    $(document).ready(function () {
        ...
    });
</script>
}

...

@Html.Partial("_Charts", Model)

но частичное представление зависело от некоторого JavaScript в разделе Scripts. Я решил это путем кодирования частичного представления в виде JSON, загрузки его в переменную JavaScript и последующего использования этого для заполнения div, поэтому:

@{
    var partial = Html.Raw(Json.Encode(new { html = Html.Partial("_Charts", Model).ToString() }));
}

@section Scripts {
<script>
    $(document).ready(function () {
        ...
        var partial = @partial;
        $('#partial').html(partial.html);
    });
</script>
}

<div id="partial"></div>
...