연습 - Blazor 앱에서 JavaScript 라이브러리 사용

완료됨

고객이 주문에 피자를 추가한 후 X 아이콘을 선택하여 확인 없이 주문에서 피자를 제거할 수 있습니다. 고객이 실수로 주문에서 피자를 제거하는 것을 방지하기 위해 피자 회사는 항목 제거에 대한 확인 프롬프트를 추가하려고 합니다.

또한 피자 회사는 고객이 실시간으로 주문 진행 상황을 확인하기를 원합니다. 주문 세부 정보 페이지를 업데이트하여 주문 상태 지속적으로 쿼리하고 페이지가 업데이트되고 있다는 피드백을 고객에게 제공해야 합니다.

이 연습에서는 클라이언트 쪽에서 JavaScript를 호출하는 데 Blazor 구성 요소의 JS interop을 사용하여 피자 배달 회사의 기존 앱을 확장합니다. 타사 JavaScript 라이브러리와 통합하여 취소 팝업을 개선하고 JavaScript에서 Blazor 메서드를 호출하여 고객 주문의 실시간 상태를 가져옵니다.

기존 앱 복제

Blazor를 사용하려면 .NET 8.0 SDK가 설치되어 있는지 확인하세요. 자세한 내용은 모든 것이 올바르게 설치되었는지 확인을 참조하세요.

  1. Visual Studio Code를 열고 위쪽 메뉴에서 터미널>새 터미널을 선택하여 통합 터미널을 엽니다.

  2. 터미널에서 프로젝트를 만들려는 디렉터리로 변경합니다.

  3. 다음 명령을 실행하여 GitHub에서 로컬 하위 디렉터리로 앱을 복제합니다.

    git clone https://github.com/MicrosoftDocs/mslearn-build-interactive-components-blazor.git BlazingPizza
    
  4. 위쪽 메뉴 모음에서 파일>폴더 열기를 선택합니다.

  5. 폴더 열기 대화 상자에서 BlazingPizza 폴더로 이동하고 폴더 선택을 선택합니다.

    Visual Studio Code에서 누락된 자산 또는 해결되지 않은 종속성에 대한 메시지를 표시하면 또는 복원을 선택합니다.

  6. 앱을 실행하고 모든 것이 올바르게 작동하는지 확인하려면 F5 키를 누르거나 실행>디버깅 시작을 선택합니다.

  7. 웹앱에서 몇 가지 피자를 선택하고 주문에 추가합니다. 주문 목록에 몇 가지 피자가 있는 상태에서 피자 중 하나의 옆에 있는 X를 선택하고 프롬프트 없이 항목이 사라지는지 확인합니다.

  8. Shift+F5를 누르거나 Run>디버깅 중지를 선택하여 앱을 중지합니다.

주문 프로세스 리팩터링

JS interop을 사용하려면 IJSRuntime 추상화를 삽입합니다.

  1. Visual Studio Code Explorer에서 Pages를 확장한 다음, Index.razor를 선택합니다.

  2. Index.razor 파일의 @inject OrderState OrderState 문 뒤에 다음과 같이 IJSRuntime 삽입을 추가합니다.

    @inject OrderState OrderState
    @inject IJSRuntime JavaScript
    
  3. 현재, 피자 함수 호출 제거에 대한 onclick 이벤트는 OrderState.RemoveConfiguredPizza(configuredPizza)) 메서드를 직접 호출합니다. 전체 <a @onclick="@(() => OrderState.RemoveConfiguredPizza(configuredPizza))" class="delete-item">❌</a> 요소를 다음 코드로 바꿉니다.

    <button type="button" class="close text-danger" aria-label="Close"
         @onclick="@(async () => await RemovePizzaConfirmation(configuredPizza))">
         <span aria-hidden="true">&times;</span>
    </button>
    
  4. 파일 끝에 있는 @code 지시문에서 네이티브 JavaScript confirm 함수를 호출하는 새 메서드를 추가합니다. 고객이 프롬프트에서 확인을 선택하면 이 메서드는 OrderState.RemoveConfiguredPizza를 호출하여 주문에서 피자를 제거합니다. 그렇지 않으면 피자는 주문에 남아 있습니다.

    async Task RemovePizzaConfirmation(Pizza removePizza)
    {
        if (await JavaScript.InvokeAsync<bool>(
            "confirm",
            $"""Do you want to remove the "{removePizza.Special!.Name}" from your order?"""))
        {
            OrderState.RemoveConfiguredPizza(removePizza);
        }
    }
    

    서버는 IJSRuntime.InvokeAsync 메서드를 사용하여 클라이언트 쪽에 confirm 함수를 호출합니다. 호출의 응답은 bool 값을 반환합니다. 확인 대화 상자의 결과가 true이면 피자가 주문에서 제거됩니다.

  5. F5 키를 누르거나 실행>디버깅 시작을 선택합니다.

  6. 앱에서 몇 가지 피자를 주문에 추가합니다.

  7. 주문에 몇 가지 피자가 있는 상태에서 피자 중 하나의 옆에 있는 X를 선택합니다. 표준 JavaScript 확인 대화 상자가 나타납니다.

    Screenshot of the default JavaScript confirm dialog.

  8. 확인을 선택하고 피자가 주문에서 제거되었는지 확인합니다. 다른 피자 옆에 있는 X를 선택하고, 확인 대화 상자에서 취소 를 선택하고, 피자가 주문에 남아 있는지 확인합니다.

  9. Shift+F5를 누르거나 Run>디버깅 중지를 선택하여 앱을 중지합니다.

Blazor 앱에 타사 JavaScript 라이브러리 추가

피자 회사는 확인 대화 상자의 단추에서 더 명확한 텍스트를 원하고 대화 상자에서 해당 브랜딩과 스타일을 사용하려고 합니다. 일부 연구 후에 표준 대화 상자의 좋은 대체 항목으로 SweetAlert라는 작은 JavaScript 라이브러리를 표준 대화 상자를 사용하기로 결정합니다.

  1. Visual Studio Code Explorer에서 Pages를 확장한 다음, _Host.cshtml을 선택합니다.

  2. _Host.cshtml 파일 끝에 있는 뒤 <script src="_framework/blazor.server.js"></script> 줄 뒤, 하지만 </body> 줄 앞에 다음 script 요소를 추가하여 SweetAlert 라이브러리를 포함합니다.

    <script src="https://cdn.jsdelivr.net/npm/sweetalert@latest/dist/sweetalert.min.js"></script>
    

    이제 SweetAlert 라이브러리를 클라이언트 쪽에서 호출할 수 있습니다.

  3. 새 라이브러리를 사용하려면 다음과 같이 Index.razor 파일에서 RemovePizzaConfirmation 메서드를 업데이트합니다.

    async Task RemovePizzaConfirmation(Pizza removePizza)
    {
        var messageParams = new
        {
            title = "Remove Pizza?",
            text = $"""Do you want to remove the "{removePizza.Special!.Name}" from your order?""",
            icon = "warning",
            buttons = new
            {
                abort = new { text = "No, leave it in my order", value = false },
                confirm = new { text = "Yes, remove pizza", value = true }
            },
            dangerMode = true
        };
    
        if (await JavaScript.InvokeAsync<bool>("swal", messageParams))
        {
            OrderState.RemoveConfiguredPizza(removePizza);
        }
    }
    

    "swal" 이름은 타사 sweetalert.js 참조에서 제공되는 JavaScript 함수의 식별자입니다. 함수를 호출하는 swal 코드는 confirm과 유사합니다. 대부분의 업데이트는 함수가 매개 변수를 수신하는 방법으로 수행됩니다. SweetAlert는 필요한 모든 설정이 포함된 JSON 개체를 수락합니다.

  4. Visual Studio Code에서 F5 키를 누르거나 실행>디버깅 시작을 선택합니다.

  5. 이제 confirm 대화 상자에 아니요. 내 주문 그대로 유지예. 피자 제거라는 두 개의 단추가 있는지 확인하고 예상대로 작동하는지 확인합니다.

    Screenshot showing the SweetAlert dialog box.

  6. Shift+F5를 누르거나 Run>디버깅 중지를 선택하여 앱을 중지합니다.

주문 상태를 실시간으로 표시하도록 주문 페이지 업데이트

고객이 피자 주문을 제출하면 내 주문 페이지는 OrderDetail 구성 요소를 사용하여 주문의 현재 상태를 표시합니다. 피자 회사는 고객이 실시간으로 주문 진행 상황을 확인하기를 원합니다. JavaScript에서 .NET 메서드를 호출하여 상태가 배달됨으로 표시될 때까지 주문 상태를 지속적으로 가져오도록 구성 요소를 업데이트합니다.

  1. Visual Studio Code Explorer에서 Pages를 확장한 다음, OrderDetail.razor를 선택합니다.

  2. OrderDetail.razor 파일에서 구성 요소 위쪽에 있는 다음 선언을 마지막 @inject 문 아래에 추가합니다.

    @implements IDisposable
    

    @implements 선언을 사용하여 Dispose 메서드를 정의할 수 있습니다.

  3. 고객에게 페이지가 업데이트 중이라는 피드백을 제공하는 회전자를 추가합니다. <div class="track-order-details">에서 @foreach 문 위에 다음 코드를 추가합니다.

    @if (IsOrderIncomplete)
    {
        <div class="spinner-grow text-danger float-right" role="status">
            <span class="sr-only">Checking your order status...</span>
        </div>
    }
    
  4. @code 지시문에서 OrderId 속성 선언 아래에 다음 멤버를 추가합니다.

    bool IsOrderIncomplete =>
        orderWithStatus is null || orderWithStatus.IsDelivered == false;
    
    PeriodicTimer timer = new(TimeSpan.FromSeconds(3));
    
  5. 기존 OnParametersSetAsync 메서드를 다음 코드로 바꿉니다.

    protected override async Task OnParametersSetAsync() =>
        await GetLatestOrderStatusUpdatesAsync();
    

    이제 이 코드는 GetLatestOrderStatusUpdatesAsync 메서드를 호출하여 주문 상태를 업데이트합니다.

  6. 업데이트된 OnParametersSetAsync 메서드 뒤에 다음 메서드를 추가합니다.

    protected override Task OnAfterRenderAsync(bool firstRender) =>
        firstRender ? StartPollingTimerAsync() : Task.CompletedTask;
    
    async Task GetLatestOrderStatusUpdatesAsync()
    {
        try
        {
            orderWithStatus = await HttpClient.GetFromJsonAsync<OrderWithStatus>(
                $"{NavigationManager.BaseUri}orders/{OrderId}");
        }
        catch (Exception ex)
        {
            invalidOrder = true;
            Console.Error.WriteLine(ex);
        }
    }
    
    async Task StartPollingTimerAsync()
    {
        while (IsOrderIncomplete && await timer.WaitForNextTickAsync())
        {
            await GetLatestOrderStatusUpdatesAsync();
            StateHasChanged();
        }
    }
    
    public void Dispose() => timer.Dispose();
    

    OrderDetail 구성 요소는 페이지가 렌더링된 후 폴링을 시작하고 주문이 배달될 때 폴링을 중지합니다. 주문 상태가 미완료인 경우 StartPollingTimerAsync 함수는 PeriodicTimer를 사용하여 다음 틱을 비동기적으로 대기합니다. 주문이 배달될 때 애니메이션 회전자가 제거되고 페이지에는 최종 주문 상태가 표시됩니다.

  7. Visual Studio Code에서 F5 키를 누르거나 실행>디버깅 시작을 선택합니다.

  8. 앱에서 피자를 주문합니다. 내 주문 화면으로 이동하고 주문이 미완료인 동안 애니메이션 빨간색 점이 나타나고 상태가 배달됨으로 표시될 때 사라지는지 확인합니다.

    Animation showing the order status changing in real-time.

  9. Shift+F5를 누르거나 Run>디버깅 중지를 선택하여 앱을 중지합니다.