Übung: Gemeinsames Nutzen von Daten in Blazor-Anwendungen

Abgeschlossen

Da Ihre App nun mit einer Datenbank verbunden ist, können Sie die Möglichkeit zum Bestellen und Konfigurieren einer Pizza für einen Kunden hinzufügen.

Blazing Pizza möchte, dass Sie den Kunden die Möglichkeit geben, die Größe ihrer Sonderpizzen zu ändern. Sie müssen die Bestellung speichern, und Sie haben sich entschieden, den Anwendungsstatus in einem Containerdienst zu speichern.

In dieser Übung übergeben Sie Daten an eine neue Komponente für die Bestellungskonfiguration und erfahren, wie Sie den App-Status in einem bereichsbezogenen OrderState-Dienst speichern.

Hinzufügen eines neuen Dialogfelds für die Bestellungskonfiguration

  1. Halten Sie die App an, falls diese noch ausgeführt wird.

  2. Klicken Sie in Visual Studio Code mit der rechten Maustaste auf den Ordner Shared, und wählen Sie Neue Datei aus.

  3. Geben Sie ConfigurePizzaDialog.razor als Dateinamen ein.

  4. Geben Sie den folgenden Code für die Benutzeroberfläche der neuen Bestellungskomponente ein:

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

    Diese Komponente ist ein Dialogfeld, in dem die ausgewählte Spezialpizza angezeigt wird und der Kunde die Pizzagröße auswählen kann.

    Die Komponente benötigt eine Spezialpizza aus der Indexseitenkomponente, um auf die Memberwerte einer Pizza zuzugreifen.

  5. Fügen Sie den Blazor-Block @code hinzu, damit Parameter an die Komponente übergeben werden können:

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

Bestellen einer Pizza

Wenn ein Kunde eine Pizza auswählt, soll das Dialogfeld dem Kunden die Möglichkeit geben, die Größe seiner Pizza zu ändern. Sie erweitern nun das Steuerelement Index.razor, um diese Interaktivität hinzuzufügen.

  1. Erweitern Sie im Datei-Explorer den Ordner Pages, und wählen Sie dann Index.razor aus.

  2. Fügen Sie im @code-Block unter der Variablen List<PizzaSpecial> den folgenden Code hinzu:

        Pizza configuringPizza;
        bool showingConfigureDialog;
    
  3. Fügen Sie Code unter der OnInitializedAsync()-Methode hinzu, um eine Pizza zu erstellen:

        void ShowConfigurePizzaDialog(PizzaSpecial special)
        {
            configuringPizza = new Pizza()
            {
                Special = special,
                SpecialId = special.Id,
                Size = Pizza.DefaultSize
            };
    
            showingConfigureDialog = true;
        }
    
  4. Gestatten Sie der Webseite, die serverseitige ShowConfigurePizzaDialog-Methode aufzurufen, indem Sie Kunden die Auswahl eines <li>-Tags für eine Pizza ermöglichen. Ersetzen Sie <li>-Zeile durch den folgenden Code:

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

    Wenn ein Kunde eine Pizza auswählt, führt der Server die ShowConfigurePizzaDialog-Methode aus, die eine Pizza anhand der Spezialpizzadaten erstellt und die Variable showingConfigureDialog auf true festlegt.

  5. Die Seite braucht eine Möglichkeit, die neue ConfigurePizzaDialog-Komponente anzuzeigen. Fügen Sie diesen Code über dem @code-Block hinzu:

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

    Die gesamte Datei index.razor sollte jetzt wie dieses Beispiel aussehen:

        @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. Wählen Sie F5 oder Ausführen aus. Wählen Sie dann Debuggen starten aus.

  7. Wählen Sie eine Pizza aus, und beobachten Sie, wie das neue Dialogfeld angezeigt wird.

    Screenshot des Dialogfelds für eine Pizzabestellung

Verwalten des Status einer Bestellung

Derzeit zeigt die App das Konfigurationsdialogfeld an, lässt jedoch nicht zu, dass Sie den Vorgang abbrechen oder mit der Bestellung der Pizza fortfahren. Um den Status der Bestellung zu verwalten, fügen Sie einen neuen Containerdienst für den Bestellstatus hinzu.

  1. Halten Sie die App an, falls diese noch ausgeführt wird.

  2. Erstellen Sie im Ordner BlazingPizza einen neuen Ordner. Nennen Sie ihn Services.

  3. Erstellen Sie im Ordner Services eine neue Datei. Nennen Sie sie OrderState.cs.

  4. Geben Sie diesen Code für die Klasse ein:

    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;
        }
    }
    

    Sie werden feststellen, dass die Index.razor-Komponente derzeit Code enthält, der in die neue Klasse verschoben werden kann. Im nächsten Schritt machen Sie diesen Dienst in der App verfügbar.

  5. Wählen Sie im Datei-Explorer die Datei Program.cs aus.

  6. Fügen Sie im Teil der Datei mit den Zeilen, die mit builder.Services. beginnen, diese Zeile hinzu:

    builder.Services.AddScoped<OrderState>();
    

    In der vorherigen Übung haben Sie hier den Datenbankkontext hinzugefügt. Dieser Code fügt den neuen Dienst OrderState hinzu. Da der Code sich nun an Ort und Stelle befindet, kann er in der index.razor-Komponente verwendet werden.

  7. Fügen Sie am Anfang der Datei die folgende using-Anweisung hinzu, um die OrderState-Klasse aufzulösen:

    using BlazingPizza.Services;
    
  8. Erweitern Sie im Datei-Explorer den Ordner Pages, und wählen Sie dann Index.razor aus.

  9. Fügen Sie am Anfang der Datei unter @inject NavigationManager NavigationManager diesen Code hinzu:

    @using BlazingPizza.Services
    @inject OrderState OrderState
    
  10. Entfernen Sie configuringPizza, showingConfigureDialog, und ShowConfigurePizzaDialog() aus dem Block @code. Dies sollte jetzt wie folgt aussehen:

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

    Es treten nun Fehler auf, wenn der gesamte Code auf die gelöschten Elemente verweist.

  11. Ändern Sie den Aufruf von ShowConfigurePizzaDialog(special)) so, dass die OrderState-Version verwendet wird:

    <li @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
    
  12. Ändern Sie den Verweis in den booleschen Wert showingConfigureDialog:

    @if (OrderState.ShowingConfigureDialog)
    
  13. Ändern Sie den Parameter mit configuringPizza:

    <ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" />
    
  14. Wählen Sie F5 oder Ausführen aus. Wählen Sie dann Debuggen starten aus.

    Wenn alles richtig ist, sehen Sie keinen Unterschied. Das Dialogfeld wird wie zuvor angezeigt.

Abbrechen und Ausführen von Pizzabestellungen

Möglicherweise haben Sie in der OrderState-Klasse zwei Methoden bemerkt, die bisher nicht verwendet wurden. Die Methoden CancelConfigurePizzaDialog und ConfirmConfigurePizzaDialog schließen das Dialogfeld und fügen die Pizza einem Order-Objekt hinzu, nachdem der Kunde die Bestellung bestätigt hat. Sie verbinden nun diese Methoden mit den Schaltflächen im Konfigurationsdialogfeld.

  1. Halten Sie die App an, falls diese noch ausgeführt wird.

  2. Erweitern Sie im Datei-Explorer den Ordner Shared. Wählen Sie dann ConfigurePizzaDialog.razor aus.

  3. Fügen Sie im @code-Block zwei neue Parameter hinzu:

      @code {
        [Parameter] public Pizza Pizza { get; set; }
        [Parameter] public EventCallback OnCancel { get; set; }
        [Parameter] public EventCallback OnConfirm { get; set; }
      }
    
  4. Den Schaltflächen können nun @onclick-Direktiven hinzugefügt werden. Ändern Sie den aktuellen Code für die Schaltflächen im Dialogfeld in das folgende 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. Im letzten Schritt werden die OrderState-Methoden zum Abbrechen und Bestätigen von Bestellungen übergeben. Erweitern Sie im Datei-Explorer den Ordner Pages. Wählen Sie dann Index.razor aus.

  6. Ändern Sie den Code für den Aufruf der ConfigurePizzaDialog-Komponente:

        <ConfigurePizzaDialog
          Pizza="OrderState.ConfiguringPizza"
          OnCancel="OrderState.CancelConfigurePizzaDialog"
          OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />
    
  7. Wählen Sie F5 oder Ausführen aus. Wählen Sie dann Debuggen starten aus.

Die App sollte es Kunden nun ermöglichen, den Vorgang abzubrechen oder eine konfigurierte Pizza zu einer Bestellung hinzuzufügen. Es gibt keine Möglichkeit, die aktuelle Bestellung anzuzeigen oder die Preise zu aktualisieren, wenn die Pizzagröße geändert wird. Diese Funktionen werden in der nächsten Übung hinzugefügt.