Отображение раздела скрипта в представлении, когда содержимое страницы отображается в DOM с помощью ответа на вызов jjuery ajax - PullRequest
0 голосов
/ 03 сентября 2018

Я использую @RenderSection("scripts", required: false) в _Layout.cshtml в нижней части страницы после того, как сценарий входит в комплект. My View с использованием этого макета определил раздел скриптов (@section scripts{ //script block}). Все работает нормально, когда я отображаю представление из действия контроллера через полный вызов страницы.

Но когда я отображаю содержимое того же представления внутри контейнера, используя обработчик вызова $ .ajax, например ($('#container').html(result)), тогда секция сценариев, определенная на странице _Layout.cshtml , не загружается и не выполняется на DOM. Обратите внимание, что в этом случае _Layout не загружается, поскольку вызов был ajax, и страница макета уже была в DOM, и я не хочу загружать страницу макета снова, чтобы улучшить время загрузки страницы. Меня интересует только загрузка содержимого дочернего представления.

Пожалуйста, найдите ниже настройки

_Layout.cshtml

 <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    @Styles.Render("~/Content/css")
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">                

            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Load Full", "LoadPartial", "Home")</li>
                    <li><a href="#" id="lnkMenu" data-url="@Url.Action("LoadPartial","Home")">Load via SPA</a></li>
                </ul>
            </div>
        </div>
    </div>
    <div id="container" class="container body-content">
        @RenderBody()
        <hr />
    </div>    
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    <script src="~/Scripts/Common.js"></script>
    @RenderSection("scripts", required: false)
</body>
</html>

Контроллер

public ViewResult LoadPartial()
    {       
        return View("_LoadPartial");
    }

_ViewStart.cshtml:

   @{
    Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
    }

Частичное представление: _LoadPartial.cshtml

     <div class="jumbotron">
        <h2>Script loading demo</h2>
    </div>
    <p id="partial-id">Partial view content</p>
    @section scripts
        {
        <script>
                $(function () {
                    console.log("full");
                    $('#partial-id').css('color', 'blue');
                });
            </script>
        }

Java-скрипт код для загрузки представления с помощью вызова ajax

    $(function () {
    $('#lnkMenu').click(function () {
        var url = $(this).data("url");
        $.ajax({
            url: url,
            type: 'GET',
            cache: false
        }).done(function (result) {
            $('#container').html(result);
        });
    });
  });

Теперь, когда я загружаю страницу, используя Layout в первом случае, она работает нормально. Но если я попытаюсь загрузить страницу, используя jquery ajax, тогда сценарий не работает.

========================= Решение, которое я пробовал ================ ===============

Чтобы исправить это, я попробовал следующее решение, т. Е. На мой взгляд, я загружаю раздел скрипта, исходя из условия, что если запрос Ajax, то запускает скрипт нормально, а если это полностраничный запрос с Layout, то запускаю секцию скрипта. С этим решением мой _LoadPartial.cshtml вид выглядит следующим образом

    <div class="jumbotron">
    <h2>Script loading demo</h2>
</div>
<p id="partial-id">Partial view content</p>
@{
    if (Request.IsAjaxRequest())
    {
        <script>
            $(function () {
                console.log("partial");     
                $('#partial-id').css('color', 'blue');
            });
        </script>
    }
    else
    {
        @section scripts
        {
        <script>
                $(function () {
                    console.log("full");
                    $('#partial-id').css('color', 'blue');
                });
            </script>
        }
    }
}

Это решение прекрасно работает в обоих случаях, но здесь проблема с решением заключается в том, что он нарушает принцип DRY , так как мне приходится писать один и тот же блок скриптов как в if, так и в остальном block.

Кто-нибудь знает, как лучше всего справляться с такими сценариями?

1 Ответ

0 голосов
/ 03 сентября 2018

$ (function () {}); просто сокращение от $ (document) .ready ({});

$ (document) .ready будет запущено только один раз после завершения начальной загрузки документа. Если я вас правильно понимаю, ваш поток выглядит следующим образом:

  1. Загрузить страницу
  2. Нажмите на ссылку, чтобы загрузить частичное представление
  3. Ajax-вызов получает частичную разметку представления с сервера и вставляет в DOM
  4. Вы ожидаете $ (function () {}); бежать в этот момент

$ (document) .ready будет вызываться между шагами 1 и 2. К тому времени, когда вы загрузите частичное представление, оно уже было вызвано и больше не будет вызываться только потому, что вы загружаете дополнительную разметку.

Я бы предложил заменить код $ (function ()) на реальную функцию и вызвать его в разделе успеха вашего ajax.

Частичное представление: _LoadPartial.cshtml

@section scripts
    {
    <script>
            function changeTextColour() {
                console.log("full");
                $('#partial-id').css('color', 'blue');
            };
        </script>
    }

JavaScript

$(function () {
$('#lnkMenu').click(function () {
    var url = $(this).data("url");
    $.ajax({
        url: url,
        type: 'GET',
        cache: false
    }).done(function (result) {
        $('#container').html(result);
        changeTextColour();
    });
});
});

=============================================== ==========

Если вам нужно более общее решение, вы можете вернуть частичную разметку представления в виде строки как часть объекта JSON, чтобы вернуть несколько значений. Вам понадобится следующий метод:

public static string RenderPartialToString(Controller controller, string partialViewName, object model, ViewDataDictionary viewData, TempDataDictionary tempData)
    {
        ViewEngineResult result = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialViewName);

        if (result.View != null)
        {
            controller.ViewData.Model = model;
            StringBuilder sb = new StringBuilder();
            using (StringWriter sw = new StringWriter(sb))
            {
                using (HtmlTextWriter output = new HtmlTextWriter(sw))
                {
                    ViewContext viewContext = new ViewContext(controller.ControllerContext, result.View, viewData, tempData, output);
                    result.View.Render(viewContext, output);
                }
            }

            return sb.ToString();
        }

        return String.Empty;
    }

Использование:

Действие:

public ActionResult Action() 
{
     var viewModel = new WhateverTypeYourViewModelIs();
     string partialHtml = RenderPartialToString(this, "PartialViewLocation.cshtml", viewModel, ViewData, TempData);
     return Json(new { Html = partialHtml, Color = "Blue" });
}

Javascript:

$(function () {
$('#lnkMenu').click(function () {
    var url = $(this).data("url");
    $.ajax({
        url: url,
        type: 'GET',
        cache: false
    }).done(function (result) {
        $('#container').html(result.Html);
        changeTextColour(result.Color);
    });
});
});

Затем вы можете просто изменить цвет в вашем действии в зависимости от того, какое действие вы вызываете. Затем вы просто зарегистрируете функцию changeTextColor () при загрузке страницы, а не в частичном представлении.

Надеюсь, что это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...