Bootstrap 4 Carousel не работает на стороне сервера Blazor (предварительная версия 7)

Я следил за решением для использования Carousel с Blazor, но получаю исключение Object при запуске приложения.

Как использовать карусель Bootstrap в Blazor

_Host.cshtml:

<body>
    <app>@(await Html.RenderComponentAsync<App>())</app>

    <script src="_framework/blazor.server.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"
            integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
            crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
            integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
            crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
            integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
            crossorigin="anonymous"></script>
    @*<script src="_framework/blazor.webassembly.js"></script>*@

    <script>
        window.initializeCarousel = () => {
            $('#mycarousel').carousel({ interval: 2000 });

            //see step 2 to understand these news id's:
            $('#mycarousel-prev').click(
                () => $('#mycarousel').carousel('prev'));
            $('#mycarousel-next').click(
                () => $('#mycarousel').carousel('next'));

        }
    </script>
</body>
</html>

Razor Page:

@page "/fullDetails/{id:int}"
@using BlazorApp2.Data
@using System.Collections.Generic
@inject IJSRuntime JsRuntime;
@inject VehicleService VService
@inherits UIAttributes


<h1>Vehicle Details</h1>
<hr />
<div>
    @if (vehicleInfo == null)
    {
        <p><em>Loading...</em></p>
    }
    else
    {
        <div class="col-lg-4 col-md-6 col-sm-6">
            <div id="mycarousel" class="carousel slide" data-ride="carousel">
                <div class="carousel-inner">
                    @foreach (var img in images)
                    {
                        if (img.SeqNo == "1")
                        {
                            <div class="carousel-item active">
                                <img class="d-block w-100" src="/images/@img.ImageName" alt="None">
                            </div>

                        }
                        else
                        {
                            <div class="carousel-item">
                                <img class="d-block w-100" src="/images/@img.ImageName" alt="None">
                            </div>
                        }
                    }
                </div>

                <!-- Left and right controls -->
                <a class="carousel-control-prev" id="mycarousel-prev" data-slide="prev">
                    <span class="carousel-control-prev-icon"></span>
                </a>
                <a class="carousel-control-next" id="mycarousel-next" data-slide="next">
                    <span class="carousel-control-next-icon"></span>
                </a>
            </div>
        </div>



</div>

@*If using @code per new speck you get errors when using this type of format  await _jsRuntime.InvokeAsync<object>("initializeCarousel"); -- where <object> while be seen as markup 08/06/2019*@

@functions{

    VehicleFullDetails vehicleInfo;
    VehicleImage[] images;
    string first { get; set; }

    [Parameter]
    int id { get; set; }


    protected override async Task OnInitAsync()
    {
        vehicleInfo = await VService.OnGetVehicleFullDetailsAsync(id);
        images = vehicleInfo.Images.ToArray();
    }

    private  IJSRuntime _jsRuntime;


    bool firstRender = true;

    protected async override Task OnAfterRenderAsync()
    {
        if (firstRender)
        {

 (line 107)           await _jsRuntime.InvokeAsync<object>("initializeCarousel");
            firstRender = false;
        }
    }



}

[2019-08-07T15: 51: 05.848Z] Ошибка: System.AggregateException: произошла одна или несколько ошибок. (Ссылка на объект не установлена ​​на экземпляр объекта.) ---> System.NullReferenceException: ссылка на объект не установлена ​​на экземпляр объекта. в BlazorApp2.Pages.FullDetails.OnAfterRenderAsync () в C: \ projects \ blazor \ GetStarted \ BlazorApp2 \ BlazorApp2 \ Pages \ FullDetails.razor: строка 107 --- Конец внутренней трассировки стека исключений ---


person T Treinen    schedule 07.08.2019    source источник


Ответы (2)


JavaScript не работает с Blazor так, как раньше работал со страницами Razor по умолчанию, поскольку серверный Blazor использует WebAssembly и передает данные пользователю в двоичном формате.

И когда <script> передается по частям, он не может работать.

Есть два способа решить вашу проблему:

1) - один из них - это изменение Blazor со стороны сервера на сторону клиента (чтобы пользователь загружал полную страницу со всеми скриптами)

2) - второй - использовать взаимодействие JavaScript, как его использовать, вы можете прочитать в официальной документации MS ASP.NET Core Blazor JavaScript interop

У вас также есть некоторые синтаксические ошибки в вашем коде:

await _jsRuntime.InvokeAsync<object>("initializeCarousel");

Но вы имеете в виду JS-скрипт, поэтому это должен быть js-файл, подобный этому:

await _jsRuntime.InvokeAsync<object>("initializeCarousel.js");

person Anton Polchenko    schedule 07.08.2019
comment
Спасибо, но это упражнение на стороне сервера. Если я правильно прочитал документацию, на стороне клиента используется скрипт веб-сборки. - person T Treinen; 08.08.2019
comment
Серверная сторона Blazor использует WebAssembly в корне неверна. Blazor Webassembly (также известный как Client Side Blazor) использует веб-сборку. Blazor на стороне сервера использует небольшой сценарий Java на стороне клиента. - Стоит проголосовать против - person Daniel Schmid; 10.11.2019

Я поместил скрипт в файл initCarousel.js и добавил его на страницу _host.cshtml. Затем я изменил свой код @function на:

 bool firstRender = true;

    protected async override Task OnAfterRenderAsync()
    {
        if (firstRender)
        {

            await jsRuntime.InvokeAsync<string>("initializeCarousel");
            firstRender = false;
        }
    }

Серверное приложение теперь циклически перебирает изображения и позволяет выбирать следующий / предыдущий.

Спасибо Крису Сэйнти за разъяснения: https://chrissainty.com/using-javascript-interop-in-razor-components-and-blazor/

person T Treinen    schedule 08.08.2019