Упражнение. Предоставление общего доступа к данным в приложениях Blazor
Теперь, когда приложение подключено к базе данных, пришло время добавить возможность для клиентов настраивать и заказывать пиццу.
Blazing Pizza хочет, чтобы вы создали возможность для клиентов изменять размер их особых пицц. Необходимо хранить заказ и сохранять состояние приложения в сервисе контейнеров.
В этом упражнении вы передаете данные в новый компонент конфигурации заказа и увидите, как сохранить состояние приложения в службе с областью OrderState.
Добавление диалогового окна настройки нового заказа
Остановите приложение, если оно по-прежнему запущено.
В Visual Studio Code щелкните правой кнопкой мыши папку Shared и выберите Новый файл.
Введите ConfigurePizzaDialog.razor в качестве имени файла.
Введите этот код для пользовательского интерфейса нового компонента заказов:
@inject HttpClient HttpClient <div class="dialog-container"> <div class="dialog"> <div class="dialog-title"> <h2>@Pizza.Special.Name</h2> @Pizza.Special.Description </div> <form class="dialog-body"> <div> <label>Size:</label> <input type="range" min="@Pizza.MinimumSize" max="@Pizza.MaximumSize" step="1" /> <span class="size-label"> @(Pizza.Size)" (£@(Pizza.GetFormattedTotalPrice())) </span> </div> </form> <div class="dialog-buttons"> <button class="btn btn-secondary mr-auto" >Cancel</button> <span class="mr-center"> Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span> </span> <button class="btn btn-success ml-auto" >Order ></button> </div> </div> </div>Этот компонент представляет собой диалоговое окно, показывающее выбранную специальную пиццу и позволяющее клиенту выбрать размер пиццы.
Компоненту необходимо использовать специальную пиццу из компонента индексной страницы для доступа к значениям членов пиццы.
Добавьте блок Blazor
@code, чтобы разрешить передаче параметров в компонент:@code { [Parameter] public Pizza Pizza { get; set; } }
Заказ пиццы
Когда клиент выбирает пиццу, диалоговое окно должно позволить им изменить размер пиццы. Давайте улучшим элемент управления index.razor, чтобы добавить интерактивные возможности.
В проводнике разверните страницы и выберите Index.razor.
Добавьте этот код в блок
@codeв переменнойList<PizzaSpecial>:Pizza configuringPizza; bool showingConfigureDialog;Добавьте этот код для создания пиццы в методе
OnInitializedAsync():void ShowConfigurePizzaDialog(PizzaSpecial special) { configuringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize }; showingConfigureDialog = true; }Позвольте веб-странице вызывать метод
ShowConfigurePizzaDialogна стороне сервера, позволяя клиентам выбрать тег<li>для пиццы. Замените строку<li>следующим кодом:<li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">Когда клиент выбирает пиццу, сервер выполняет метод
ShowConfigurePizzaDialog, который создает пиццу со специальными данными пиццы и задает для переменнойshowingConfigureDialogзначениеtrue.На странице нужен способ отображения нового компонента
ConfigurePizzaDialog. Добавьте этот код над блоком@code:@if (showingConfigureDialog) { <ConfigurePizzaDialog Pizza="configuringPizza" /> }Теперь весь файл
index.razorдолжен выглядеть следующим образом:@page "/" @inject HttpClient HttpClient @inject NavigationManager NavigationManager <div class="main"> <h1>Blazing Pizzas</h1> <ul class="pizza-cards"> @if (specials != null) { @foreach (var special in specials) { <li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')"> <div class="pizza-info"> <span class="title">@special.Name</span> @special.Description <span class="price">@special.GetFormattedBasePrice()</span> </div> </li> } } </ul> </div> @if (showingConfigureDialog) { <ConfigurePizzaDialog Pizza="configuringPizza" /> } @code { List<PizzaSpecial> specials = new(); Pizza configuringPizza; bool showingConfigureDialog; protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); } void ShowConfigurePizzaDialog(PizzaSpecial special) { configuringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize }; showingConfigureDialog = true; } }Выберите F5 или выберите Выполнить. Затем выберите Начать отладку.
Выберите пиццу и просмотрите новое диалоговое окно.
Управлять состоянием заказа
На данный момент приложение отображает диалоговое окно конфигурации, но не позволяет отменить или перейти к заказу пиццы. Чтобы управлять состоянием заказа, добавьте новую службу управления состоянием заказа.
Остановите приложение, если оно по-прежнему запущено.
Создайте новую папку в папке BlazingPizza. Назовите это службы.
Создайте новый файл в папке Services. Назовите его OrderState.cs.
Введите этот код для класса:
namespace BlazingPizza.Services; public class OrderState { public bool ShowingConfigureDialog { get; private set; } public Pizza ConfiguringPizza { get; private set; } public Order Order { get; private set; } = new Order(); public void ShowConfigurePizzaDialog(PizzaSpecial special) { ConfiguringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize, Toppings = new List<PizzaTopping>(), }; ShowingConfigureDialog = true; } public void CancelConfigurePizzaDialog() { ConfiguringPizza = null; ShowingConfigureDialog = false; } public void ConfirmConfigurePizzaDialog() { Order.Pizzas.Add(ConfiguringPizza); ConfiguringPizza = null; ShowingConfigureDialog = false; } }Обратите внимание, что в данный момент в компоненте index.razor есть код, который можно переместить в новый класс. Следующий шаг — сделать эту службу доступной в приложении.
В проводнике выберите Program.cs.
В части файла со строками, начинающимися с
builder.Services., добавьте следующую строку:builder.Services.AddScoped<OrderState>();Из предыдущего упражнения мы добавили здесь контекст базы данных. Этот код добавляет новую службу
OrderState. Теперь этот код можно использовать в компонентеindex.razor.Добавьте следующую
usingдирективу в начало файла. Эта директива обрабатывает все ссылки на классOrderState.using BlazingPizza.Services;В проводнике разверните страницы и выберите Index.razor.
В верхней части файла в
@inject NavigationManager NavigationManagerдобавьте следующий код:@using BlazingPizza.Services @inject OrderState OrderStateУдалите
configuringPizza,showingConfigureDialogиShowConfigurePizzaDialog()из блока@code. Теперь он должен выглядеть следующим образом:@code { List<PizzaSpecial> specials = new List<PizzaSpecial>(); protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); } }Теперь возникают ошибки, когда код ссылается на удаленные элементы.
Измените вызов на
ShowConfigurePizzaDialog(special)), чтобы использовать версию OrderState:<li @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">Измените ссылку на логический
showingConfigureDialog:@if (OrderState.ShowingConfigureDialog)Изменение параметра с помощью
configuringPizza:<ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" />Выберите F5 или выберите Выполнить. Затем выберите Начать отладку.
Если все правильно, вы не должны видеть никакой разницы. Диалоговое окно отображается так же, как и раньше.
Отмена и выполнение заказов на пиццу
Возможно, в классе OrderState есть два метода, которые еще не используются. Методы CancelConfigurePizzaDialog и ConfirmConfigurePizzaDialog закрывают диалоговое окно и добавляют пиццу в объект Order, после того как клиент подтвердит заказ. Давайте подключим эти методы к кнопкам диалогового окна конфигурации.
Остановите приложение, если оно по-прежнему запущено.
В проводнике разверните общие. Затем выберите ConfigurePizzaDialog.razor.
В блоке
@codeдобавьте два новых параметра:@code { [Parameter] public Pizza Pizza { get; set; } [Parameter] public EventCallback OnCancel { get; set; } [Parameter] public EventCallback OnConfirm { get; set; } } `` `Теперь к кнопкам могут быть добавлены директивы
@onclick. Измените нынешний код для кнопок диалогового окна на следующую разметку:<div class="dialog-buttons"> <button class="btn btn-secondary mr-auto" @onclick="OnCancel">Cancel</button> <span class="mr-center"> Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span> </span> <button class="btn btn-success ml-auto" @onclick="OnConfirm">Order ></button> </div>Последний шаг — передать методы
OrderStateдля отмены и подтверждения заказов. В проводнике разверните Pages. Затем выберите Index.razor.Измените код для вызова компонента
ConfigurePizzaDialog:<ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" OnCancel="OrderState.CancelConfigurePizzaDialog" OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />Выберите F5 или выберите Выполнить. Затем выберите Начать отладку.
Теперь приложение должно позволить клиентам отменить или добавить настроенную пиццу в заказ. У нас нет способа показать текущий заказ или обновить цены при изменении размера пиццы. Мы добавим эти функции в следующем упражнении.