Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use alert(),confirm() and prompt() function using Blazor?

I am learning the Blazor technology. I started a default increment project in VS 2019 and I have modified the code for Decrement with confirm() and alert but it does not work.

 @page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Increment</button>
<button class="btn btn-primary btn-danger" onclick="if (confirm('Are you sure to Decrement')) { @DecrementCount() }">Decrement</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }

    private void DecrementCount()
    {
        currentCount--;
        // alert('Operation Successfully executed')
    }
}

In my code snippet confirm() function works perfectly but I want to call a Decrement function is not working build failed. And I would like to add a success message in my function. Please provide any option instead of using confirm(),alert() functions.

like image 231
Prasanna Kumar J Avatar asked Mar 20 '20 11:03

Prasanna Kumar J


People also ask

What is prompt alert and confirm in JavaScript?

A prompt box is often used if you want the user to input a value before entering a page. When a prompt box pops up, the user will have to click either "OK" or "Cancel" to proceed after entering an input value. If the user clicks "OK" the box returns the input value. If the user clicks "Cancel" the box returns null.

What is Blazor in asp net core?

Blazor is a feature of ASP.NET, the popular web development framework that extends the . NET developer platform with tools and libraries for building web apps.


2 Answers

Unfortunately, there is not implementation of such useful functions in Blazor yet.
So you need to use JSRuntime instance.

@inject IJSRuntime JsRuntime

...

@code
{
    //...

    await JsRuntime.InvokeVoidAsync("alert", "Warning!"); // Alert

    bool confirmed = await JsRuntime.InvokeAsync<bool>("confirm", "Are you sure?"); // Confirm
    string prompted = await JsRuntime.InvokeAsync<string>("prompt", "Take some input:"); // Prompt

    //...
}

It makes possible to execute JS code right inside your C# code. With that you can use any JS logic you want to create behaviour you need.

See docs for details.

like image 137
picolino Avatar answered Oct 23 '22 11:10

picolino


I am new to Blazor and a replacement for JavaScript Alert, Confirm, and Prompt was one of the first things on my list. I came up with a service in Blazor Server / BlazorWebView (I haven't tested in Web Assembly). The <Modal> component we'll create can be controlled by the service or directly from JavaScript. Although, if you don't need to call the <Modal> via JavaScript than you can remove any JavaScript or IJSRuntime references.

The ModalService.cs is very simple. It has an OnShow event that we can hook into our <Modal> component later. The event is a function that takes prameters ModalType, title, body and it returns a dynamic task.

Setup

ModalService.cs

namespace MyProjectName.Services
{
    public class ModalService
    {
        
        public event Func<ModalBase.ModalType, string, string,Task<dynamic>> OnShow;

        public async Task<dynamic> Show(ModalBase.ModalType mType, string title, string body)
        {
            if(OnShow != null)
                return await OnShow?.Invoke(mType, title, body);
            return null;
        }

    }
}

The ModalBase.cs will be inherited by our <Modal> component. It handles opening and closing the modal. Here is where we can also attach to the ModalService event OnShow and hook up support for JavaScript invoking.

ModalBase.cs

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace MyProjectName.Services
{

    public class ModalBase : ComponentBase, IDisposable
    {

        [Inject] ModalService ModalService { get; set; }
        [Inject] IJSRuntime JS { get; set; }

        public enum ModalType
        {
            Alert,
            Prompt,
            Confirm
        }

        protected override void OnInitialized()
        {
            // Attach to our service event.
            ModalService.OnShow += Show;
        }

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            // Set a JavaScript referene for our DotNet interop.
            if(firstRender)
                await JS.InvokeVoidAsync("MODAL.SetDotnetReference", DotNetObjectReference.Create(this));
        }



        public string Title { get; set; }
        public string Body { get; set; }


        public Guid Guid = Guid.NewGuid();
        public string ModalDisplay = "none;";
        public string ModalClass = "";
        public bool ShowBackdrop = false;


        public string PromptValue { get; set; }
        private bool ConfirmValue { get; set; }
        public ModalType MType { get; set; }


   
      
        private List<string> MsgIds = new List<string>();
        [JSInvokable("Show")]
        public async Task<dynamic> Show(ModalType mType, string title, string body)
        {
            // The JavaScript call MODAL.DotNetReference.invokeMethodAsync is non-blocking
            // This means multiple calls to show the modal using invokeMethodAsync will only show the modal once.
            // We can solve this by making sure each message waits in line.
            string msgId = Guid.NewGuid().ToString();

            if (!MsgIds.Contains(msgId))
                MsgIds.Add(msgId);

            // If multiple messages are being processed, wait for this msgs turn.
            while (MsgIds.Count > 1 && MsgIds.IndexOf(msgId) != 0)
                await Task.Delay(250);

            Title = title;
            Body = body;
            ModalDisplay = "block;";
            ModalClass = "Show";
            MType = mType;
            ShowBackdrop = true;
            StateHasChanged();

            while (ShowBackdrop)
                await Task.Delay(250);

            switch (mType)
            {
                default:
                case ModalType.Alert:
                    MsgIds.Remove(msgId);
                    return string.Empty;
                case ModalType.Confirm:
                    bool confirmResponse = ConfirmValue;
                    MsgIds.Remove(msgId);
                    return confirmResponse;
                case ModalType.Prompt:
                    string promptResponse = PromptValue;
                    MsgIds.Remove(msgId);
                    return promptResponse;
            }

        }

        public void Close(bool isCancel)
        {
            // Determine returned values.
            PromptValue = isCancel ? string.Empty : PromptValue;
            ConfirmValue = isCancel ? false : true;
            ModalDisplay = "none";
            ModalClass = "";
            ShowBackdrop = false;
            StateHasChanged();
        }

        public void Dispose()
        {
            ModalService.OnShow -= Show;
        }
    }
}

I designed the <Modal> component based off the bootstrap markup discussed here. The major difference is I that have moved the guts into ModalBase.cs to interact with our service.

Modal.razor

@using Microsoft.JSInterop
@using MyProjectName.Services
@inherits ModalBase
<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay; overflow-y: auto;">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title w-100 text-center" style="padding-left:31px">@Title</h5>
                <button type="button" class="close border-0 bg-white" data-dismiss="modal" aria-label="Close"  @onclick="() => Close(true)">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body mx-auto text-center text-break">
                @Body
                @if (MType == ModalType.Prompt){ 
                    <input type="text" class="form-control text-center my-2" @bind-value="PromptValue" style="max-width:400px"></input> 
                }
            </div>
            <div class="modal-footer justify-content-center">
                @if (MType == ModalType.Prompt || MType == ModalType.Confirm)
                {
                    <button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => Close(false)">OK</button>
                    <button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => Close(true)">Cancel</button>
                }
                else
                {
                    <button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => Close(false)">Close</button>
                }
            </div>
        </div>
    </div>
</div>

@if (ShowBackdrop)
{
    <div class="modal-backdrop fade show"></div>
}

Usage

Include the ModalService into our service collection.

Program.cs

builder.Services.AddScoped<ModalService>();

MainLayout.razor

@using MyProjectName.Components    
@inherits LayoutComponentBase

<PageTitle>My Project</PageTitle>

<Modal></Modal>
<div class="page">
    .
    .
    .
</div>

Inject and use the service somewhere in your application.

Index.razor

@code
{
    [Inject] public ModalService ModalService { get; set; }


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            if (await ModalService.Show(Modal.ModalType.Confirm,"Save Settings", "Are you sure you want to save settings?"))
            {
                string fileName = await ModalService.Show(Modal.ModalType.Prompt, "File Name", "Please enter a filename");
                if (!string.IsNullOrEmpty(fileName))
                    await ModalService.Show(Modal.ModalType.Alert, "File Saved Success", $"File Saved as {fileName}");
                else
                    await ModalService.Show(Modal.ModalType.Alert, "File Saved Cancelled", $"No file name was entered.");

            }
        }

     //   return base.OnAfterRenderAsync(firstRender);
    }
}

JavaScript Usage

// Defined somewhere globally
var MODAL = {};
MODAL.DotNetReference = null;
MODAL.SetDotnetReference = function (pDotNetReference) {
    MODAL.DotNetReference = pDotNetReference;
};
MODAL.MType = {
    Alert: 0,
    Prompt:1,
    Confirm: 2,
};

// Called from wherever
MODAL.DotNetReference.invokeMethodAsync('Show', MODAL.MType.Prompt, `Title goes here`, `Body goes here`)
.then(data => {
    console.log(`Prompt Response`, data);
});

JavaScript Note: Polyfil recommended for promise support in older browsers

Note: If you need to show the modal at earlier points in the application lifecycle, such as OnInitializedAsync, than you'll need to change ServerPrerendered to Server.

@*<component type="typeof(App)" render-mode="ServerPrerendered" />*@
<component type="typeof(App)" render-mode="Server" />
like image 23
clamchoda Avatar answered Oct 23 '22 11:10

clamchoda