Exercícios: compartilhar dados em aplicativos Blazor
Agora que seu aplicativo está conectado a um banco de dados, é hora de adicionar a capacidade de pedir e configurar a pizza de um cliente.
A Blazing Pizza quer que você permita aos clientes a capacidade de alterar o tamanho das pizzas especiais. Você precisa armazenar o pedido, e optou por armazenar o estado do aplicativo em um serviço de contêiner.
Neste exercício, você transmitirá dados para um novo componente de configuração de pedido e verá como armazenar o estado do aplicativo em um serviço com escopo OrderState.
Adicionar uma caixa de diálogo de configuração de novo pedido
Interrompa o aplicativo se ele ainda estiver em execução.
No Visual Studio Code, clique com o botão direito do mouse na pasta Compartilhado e selecione Novo Arquivo.
Insira ConfigurePizzaDialog.razor como o nome do arquivo.
Insira este código para a interface do usuário do componente de novo pedido:
@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>
Esse componente é uma caixa de diálogo que mostra a pizza especial selecionada e permite que o cliente selecione o tamanho da pizza.
O componente precisa de uma pizza especial do componente de página de índice para acessar os valores de membro de uma pizza.
Adicione o bloco
@code
do Blazor para permitir que os parâmetros sejam passados para o componente:@code { [Parameter] public Pizza Pizza { get; set; } }
Pedir uma pizza
Quando um cliente seleciona uma pizza, a caixa de diálogo deve permitir que ele altere o tamanho da pizza. Vamos aprimorar o controle de index.razor para adicionar essa interatividade.
No explorador de arquivos, expanda Páginas e selecione Index.razor.
Adicione esse código no bloco
@code
sob a variávelList<PizzaSpecial>
:Pizza configuringPizza; bool showingConfigureDialog;
Adicione o código para criar uma pizza sob o método
OnInitializedAsync()
:void ShowConfigurePizzaDialog(PizzaSpecial special) { configuringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize }; showingConfigureDialog = true; }
Permita que a página da Web chame o método
ShowConfigurePizzaDialog
do lado do servidor, permitindo que os clientes selecionem uma tag<li>
de pizza. Substitua a linha<li>
por este código:<li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
Quando um cliente seleciona uma pizza, o servidor executa o método
ShowConfigurePizzaDialog
que cria uma pizza com os dados da pizza especial e define a variávelshowingConfigureDialog
comotrue
.A página precisa de uma maneira de exibir o novo componente
ConfigurePizzaDialog
. Adicione este código acima do bloco@code
:@if (showingConfigureDialog) { <ConfigurePizzaDialog Pizza="configuringPizza" /> }
Agora, o arquivo
index.razor
deve ser parecido com este exemplo:@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; } }
Selecione F5 ou Executar. Selecione Iniciar Depuração.
Escolha uma pizza e veja a nova caixa de diálogo.
Manipular o estado de um pedido
No momento, o aplicativo mostra a caixa de diálogo de configuração, mas não permite que você cancele ou já faça o pedido da pizza. Para gerenciar o estado do pedido, você adicionará um serviço de contêiner de estado de novo pedido.
Interrompa o aplicativo se ele ainda estiver em execução.
Crie uma nova pasta na pasta BlazingPizza. Nomeie-a como Serviços.
Crie um novo arquivo na pasta Serviços. Nomeie-o como OrderState.cs.
Insira este código para a classe:
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; } }
Você verá que há código atualmente no componente index.razor que podemos mover para a nova classe. A próxima etapa é disponibilizar esse serviço no aplicativo.
No explorador de arquivos, selecione Program.cs.
Na parte do arquivo com as linhas que começam com
builder.Services.
, adicione esta linha:builder.Services.AddScoped<OrderState>();
No exercício anterior, adicionamos nosso contexto de banco de dados aqui. Esse código adiciona o novo serviço
OrderState
. Com o código aplicado, agora podemos usá-lo no componenteindex.razor
.Adicione a seguinte diretiva
using
ao topo do arquivo para resolver a classeOrderState
:using BlazingPizza.Services;
No explorador de arquivos, expanda Páginas e selecione Index.razor.
Na parte superior do arquivo, em
@inject NavigationManager NavigationManager
, adicione este código:@using BlazingPizza.Services @inject OrderState OrderState
Remova
configuringPizza
,showingConfigureDialog
eShowConfigurePizzaDialog()
do@code
bloco. Agora, ele deve ser assim:@code { List<PizzaSpecial> specials = new List<PizzaSpecial>(); protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); } }
Agora, há erros onde todo o código faz referência ao que foi excluído.
Altere a chamada a
ShowConfigurePizzaDialog(special))
para usar a versão de OrderState:<li @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
Altere a referência para o booliano
showingConfigureDialog
:@if (OrderState.ShowingConfigureDialog)
Altere o parâmetro usando
configuringPizza
:<ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" />
Selecione F5 ou Executar. Selecione Iniciar Depuração.
Se tudo estiver correto, você não verá nenhuma diferença. A caixa de diálogo é exibida como antes.
Cancelar e fazer pedidos de pizza
Talvez você tenha observado na classe OrderState dois métodos que ainda não foram usados. Os métodos CancelConfigurePizzaDialog
e ConfirmConfigurePizzaDialog
fecharão a caixa de diálogo e adicionarão a pizza a um objeto Order
se o cliente tiver confirmado o pedido. Vamos conectar esses métodos aos botões da caixa de diálogo de configuração.
Interrompa o aplicativo se ele ainda estiver em execução.
No explorador de arquivos, expanda Compartilhado. Selecione ConfigurePizzaDialog.razor.
No bloco
@code
, adicione dois novos parâmetros:@code { [Parameter] public Pizza Pizza { get; set; } [Parameter] public EventCallback OnCancel { get; set; } [Parameter] public EventCallback OnConfirm { get; set; } }
Agora, os botões podem ter diretivas
@onclick
adicionadas. Altere o código atual dos botões da caixa de diálogo para esta marcação:<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>
A última etapa é transmitir os métodos
OrderState
para cancelar e confirmar pedidos. No explorador de arquivos, expanda Páginas. Depois, selecione Index.razor.Altere o código da chamada para o componente
ConfigurePizzaDialog
:<ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" OnCancel="OrderState.CancelConfigurePizzaDialog" OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />
Selecione F5 ou Executar. Selecione Iniciar Depuração.
Agora, o aplicativo deve permitir que os clientes cancelem ou adicionem uma pizza configurada a um pedido. Não temos como mostrar o pedido atual ou atualizar os preços quando o cliente muda o tamanho da pizza. Adicionaremos esses recursos no próximo exercício.