How to do client-side UI events in Blazor

拜拜、爱过 提交于 2020-08-22 03:33:27

问题


I just started playing around with Blazor and I can already see the great potential of this new framework.

I'm wondering, though, how it will handle doing simple things like setting focus on an input control? For instance, after I handle a click event, I want to set the focus to a text input control. Do I have to use JQuery for something like that, or will Blazor have some built-in methods for that sort of thing?

Thanks

Update: I posted an answer below with an example of how to set the focus to a control by invoking a JavaScript function from the .Net code.

As of right now (Blazor 0.9.0) you create your JavaScript functions in the Index.html (or reference them from Index.html) and then in your Blazor page or component you call JsRuntime.InvokeAsync("functionName", parms);

https://docs.microsoft.com/en-us/aspnet/core/razor-components/javascript-interop


回答1:


Blazor is just the replacement (to be more precise "value addition") to the javascript. It is a client side only solution (but may be with some easy binding to ASP.Net in the future).

Still its completely based on html, and CSS. C# is replacing the js part using web assembly. So nothing has changed on how you access / modify html controls.

As of now (version 0.1.0) you have to rely on HTML DOM focus() Method to do what you intent to do (yes you have to use javascript as of now :( ).

// Not tested code
// This is JavaScript. 
// Put this inside the index.html. Just below <script type="blazor-boot"></script>
<script>
    Blazor.registerFunction('Focus', (controlId) => {
      return document.getElementById(controlId).focus();
    });
</script>

//and then wrap it for calls from .NET:    
// This is C#

public static object Focus(string controlId)
{
    return RegisteredFunction.Invoke<object>("Focus", controlId);
    //object type is used since Invoke does not have a overload for void methods. Don't know why. 
    //this will return undifined according to js specs
}

for more information you can refer below.

If you want to improve the pakaging of js neatly. you can do something like this. https://stackoverflow.com/a/49521216/476609

public class BlazorExtensionScripts : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{

    protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "script");
        builder.AddContent(1, "Blazor.registerFunction('Focus', (controlId) => { document.getElementById(controlId).focus(); });");
        builder.CloseElement();
    }

    public static void Focus(string controlId)
    {
         RegisteredFunction.Invoke<object>("Focus", controlId);
    }
}

then add this component to the root. (App.cshtml)

<BlazorExtensionScripts></BlazorExtensionScripts>
<Router AppAssembly=typeof(Program).Assembly />



回答2:


I want to add a more up-to-date (as of 0.9.0) example of calling a JavaScript function to set the focus to another control after some event, like clicking on a button. This might be helpful for someone just starting out with Blazor (like me).

This example builds on the example code in the Blazor documentation "Build Your First Blazor Components App" at https://docs.microsoft.com/en-us/aspnet/core/tutorials/build-your-first-razor-components-app?view=aspnetcore-3.0

First, follow all the instructions in the documentation. When you have a working To-Do List page, then add the following:

  1. At the bottom of Index.html, under wwwroot, and below the script tag that loads the webassembly.js, add the following script:
<script>
        window.MySetFocus = (ctrl) => {
            document.getElementById(ctrl).focus();
            return true;
        }
</script>
  1. At the top of your todo.cshtml page, add the following using statement:
@inject IJSRuntime JsRuntime;
  1. In the @functions section of your todo.cshtml page, add the following function:
    async void Focus(string controlId)
    {
        var obj = JsRuntime.InvokeAsync<string>(
            "MySetFocus", controlId);
    }

  1. In the AddToDo() function, just below the line where you set the "newToDo" variable to an empty string, add a call to the Focus function, passing in the string id of the input control. (The example in the docs does not assign an ID to the input control, so just add one yourself. I named mine "todoItem").

void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
            Focus("todoItem"); // this is the new code
        }
    }

  1. Build and run your app. When you click the add new item button, the new item should be added to the list, the input control blanked out, and the focus should be back in the input control, ready for another item to be added.



回答3:


You can't directly call JavaScript function. You are required to first register your functions like,

<script>
 Blazor.registerFunction('ShowControl', (item) => {       
     var txtInput = document.getElementById("txtValue");         
     txtInput.style.display = "";
     txtInput.value = item;
     txtInput.focus();          
});
return true;
</script>

Then you need to declare a method in C# which calls this JavaScript function. Like,

private void CallJavaScript()
{
   RegisteredFunction.Invoke<bool>("ShowControl", itemName);
}

You can call this C# method on click of button. Like,

<button id="btnShow" class="btn btn-primary" @onclick(CallJavaScript)>Show</button>

This post Create a CRUD App using Blazor and ASP.NET Core shows a working demo of calling JavaScript from Blazor.



来源:https://stackoverflow.com/questions/49460516/how-to-do-client-side-ui-events-in-blazor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!