Esercizio: Condividere dati nelle applicazioni Blazor

Completato

Ora che l'app è connessa a un database, è necessario aggiungere la funzionalità per ordinare e configurare la pizza di un cliente.

Blazing Pizza richiede l'implementazione di una funzionalità che consenta ai clienti di modificare le dimensioni delle pizze speciali. È necessario archiviare l'ordine e si è scelto di archiviare lo stato dell'applicazione in un servizio contenitore.

In questo esercizio si passeranno dati a un nuovo componente di configurazione ordini e si vedrà come archiviare lo stato dell'app in un servizio con ambito OrderState.

Aggiungere una nuova finestra di dialogo di configurazione ordini

  1. Arrestare l'app se è ancora in esecuzione.

  2. In Visual Studio Code fare clic con il pulsante destro del mouse sulla cartella Shared e scegliere Nuovo file.

  3. Immettere ConfigurePizzaDialog.razor come nome file.

  4. Immettere questo codice per l'interfaccia utente del nuovo componente per l'ordinazione:

    @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>
    

    Questo componente è una finestra di dialogo che mostra la pizza speciale selezionata e consente al cliente di selezionarne le dimensioni.

    Il componente richiede una pizza speciale ottenuta dal componente della pagina dell'indice per accedere ai valori membro di una pizza.

  5. Aggiungere il blocco Blazor @code per consentire il passaggio dei parametri al componente:

    @code {
        [Parameter] public Pizza Pizza { get; set; }
    }
    

Ordinare una pizza

Quando un cliente seleziona una pizza, la finestra di dialogo deve consentire loro di cambiarne le dimensioni. A questo punto è possibile migliorare il controllo index.razor per aggiungere questa interattività.

  1. In Esplora file espandere Pages e quindi selezionare Index.razor.

  2. Aggiungere questo codice nel blocco @code nella variabile List<PizzaSpecial>:

        Pizza configuringPizza;
        bool showingConfigureDialog;
    
  3. Aggiungere questo codice per creare una pizza nel metodo OnInitializedAsync():

        void ShowConfigurePizzaDialog(PizzaSpecial special)
        {
            configuringPizza = new Pizza()
            {
                Special = special,
                SpecialId = special.Id,
                Size = Pizza.DefaultSize
            };
    
            showingConfigureDialog = true;
        }
    
  4. Consentire alla pagina Web di chiamare il metodo lato server ShowConfigurePizzaDialog consentendo ai clienti di selezionare il tag <li> di una pizza. Sostituire la riga <li> con il codice seguente:

    <li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
    

    Quando un cliente seleziona una pizza, il server esegue il metodo ShowConfigurePizzaDialog che crea una pizza con i dati della pizza speciale e imposta la variabile showingConfigureDialog su true.

  5. La pagina richiede una soluzione per visualizzare il nuovo componente ConfigurePizzaDialog. Aggiungere questo codice sopra il blocco @code:

    @if (showingConfigureDialog)
    {
        <ConfigurePizzaDialog Pizza="configuringPizza" />
    }
    

    L'intero file index.razor dovrebbe essere simile a quello nell'esempio seguente:

        @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;
          }
        }
    
  6. Premere F5 o selezionare Esegui. Selezionare quindi Avvia debug.

  7. Selezionare una pizza e osservare la nuova finestra di dialogo.

    Screenshot che mostra la finestra di dialogo per ordinare la pizza.

Gestire lo stato di un ordine

Al momento, l'app mostra la finestra di dialogo di configurazione, ma non consente di annullare o passare all'ordinazione della pizza. Per gestire lo stato dell'ordine, si aggiungerà un nuovo servizio contenitore per lo stato dell'ordine.

  1. Arrestare l'app se è ancora in esecuzione.

  2. Creare una nuova cartella nella cartella BlazingPizza. Assegnare alla cartella il nome Services.

  3. Creare un nuovo file nella cartella Services. Assegnare al file il nome OrderState.cs.

  4. Immettere il codice seguente per la 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;
        }
    }
    

    Si noterà che attualmente nel componente index.razor è presente codice che è possibile spostare nella nuova classe. Il passaggio successivo consiste nel rendere disponibile questo servizio nell'app.

  5. In Esplora file selezionare Program.cs.

  6. Aggiungere questa riga nella parte del file con le righe che iniziano con builder.Services.:

    builder.Services.AddScoped<OrderState>();
    

    È stato aggiunto qui il contesto del database dall'esercizio precedente. Questo codice consente di aggiungere aggiunge il nuovo servizio OrderState. Dopo aver inserito questo codice, è ora possibile usarlo nel componente index.razor.

  7. Aggiungere la direttiva using seguente all'inizio del file per risolvere la classe OrderState:

    using BlazingPizza.Services;
    
  8. In Esplora file espandere Pages e quindi selezionare Index.razor.

  9. Nella parte iniziale del file aggiungere il codice seguente in @inject NavigationManager NavigationManager:

    @using BlazingPizza.Services
    @inject OrderState OrderState
    
  10. Rimuovere configuringPizza, showingConfigureDialog e ShowConfigurePizzaDialog() dal blocco @code. L'aspetto dovrebbe risultare simile al seguente:

    @code {
        List<PizzaSpecial> specials = new List<PizzaSpecial>();
    
        protected override async Task OnInitializedAsync()
        {
            specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials");
        }
    }
    

    Sono ora presenti errori nei punti in cui sono stati eliminati tutti i riferimenti al codice.

  11. Modificare la chiamata a ShowConfigurePizzaDialog(special)) per usare la versione di OrderState:

    <li @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
    
  12. Modificare il riferimento al valore booleano showingConfigureDialog:

    @if (OrderState.ShowingConfigureDialog)
    
  13. Modificare il parametro usando configuringPizza:

    <ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" />
    
  14. Premere F5 o selezionare Esegui. Selezionare quindi Avvia debug.

    Se tutto è corretto, non si dovrebbe notare alcuna differenza. La finestra di dialogo viene visualizzata come in precedenza.

Ordinare pizze e annullare gli ordini

Si potrebbe aver notato che nella classe OrderState sono presenti due metodi che non sono stati ancora usati. I metodi CancelConfigurePizzaDialog e ConfirmConfigurePizzaDialog consentono di chiudere la finestra di dialogo e aggiungere la pizza a un oggetto Order se il cliente ha confermato l'ordine. A questo punto si connetteranno questi metodi ai pulsanti della finestra di dialogo di configurazione.

  1. Arrestare l'app se è ancora in esecuzione.

  2. In Esplora file espandere Shared. Selezionare quindi ConfigurePizzaDialog.razor.

  3. Nel blocco @code aggiungere due nuovi parametri:

      @code {
        [Parameter] public Pizza Pizza { get; set; }
        [Parameter] public EventCallback OnCancel { get; set; }
        [Parameter] public EventCallback OnConfirm { get; set; }
      }
    
  4. Ai pulsanti è ora possibile aggiungere direttive @onclick. Modificare il codice corrente per i pulsanti della finestra di dialogo in questo markup:

      <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>
    
  5. L'ultimo passaggio consiste nel passare i metodi OrderState per annullare e confermare gli ordini. In Esplora file espandere Pages. Selezionare quindi Index.razor.

  6. Modificare il codice per la chiamata al componente ConfigurePizzaDialog:

        <ConfigurePizzaDialog
          Pizza="OrderState.ConfiguringPizza"
          OnCancel="OrderState.CancelConfigurePizzaDialog"
          OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />
    
  7. Premere F5 o selezionare Esegui. Selezionare quindi Avvia debug.

L'app dovrebbe ora consentire ai clienti di annullare o aggiungere una pizza configurata a un ordine. Non esiste alcun modo per visualizzare l'ordine corrente o aggiornare i prezzi quando vengono modificate le dimensioni della pizza. Queste funzionalità verranno aggiunte nell'esercizio successivo.