Blazor : how to create a component
![Blazor : how to create a component](/content/images/size/w2000/2023/10/Blazor-1.png)
Basics
Here are the different steps for the creation of a Blazor component with some javascript logic inside.
- Install Node.js
2. Create a Blazor wasm project (MyComp.Tester
)
This project will be useful to test your component.
3. In the solution, add a Razor class
project (MyComp
)
This is where your component will be implemented.
4. Add Microsoft.TypeScript.Build
nuget package to MyComp
Optional but recommended. This package lets you write your logic in typescript instead of javascript which improves the overall readability of code. Typescript is transpiled into javascript at build time to be then used by your component at runtime.
5. Generate and edit your tsconfig.json
Execute the following line from the root folder of MyComp
npx -p typescript tsc --init
You should now see a tsconfig.json
file in your project.
Open it and change module: "commonjs"
to module: "ES6"
.
Note: I've seen people do that in the project properties, in a category named TypeScript
. It never worked for me, that's why I'm offering the node.js method here. There is also the option of creating the file manually.
6. Add a typescript file in wwwroot
Add a file named mycomp.ts
and add some code as shown below:
// By convention, use the same name as your razor component (not strictly required though)
class Component1 {
public repeat(message: string) {
alert(message);
}
}
// In this code, the class is not accessible (has no export)
// The method below is exported and can be accessed through Js interop in C#.
// It'll help us get an instance of the class above
export function GetInstance() {
return new Component1();
}
Note: Why can't I attach my .ts file directly to my C# component ?
The conventions designed by Microsoft let you add a .ts file to your razor class only for pages. If you take the Counter.razor.cs
for instance, you can create a Counter.razor.ts
in the same folder and it'll fall under the razor component. You can then invoke it with a relative path (./Shared/Counter.razor.js
).
Unfortunately, this convention does not work with razor class projects. You must add your ts file in wwwroot
, and it's gonna be available at ./_content/MyComp/mycomp.ts
according to the following pattern : ./_content/<project_name>/<path under wwwroot>/script.js
.
7. Implement your js interop class
Use the provided example code and rename the class to ComponentJsInterop
.
With our current ts file, all you need to do is edit the path to the js script with the one specified above, rename Prompt
into Repeat
for clarity and change its implementation with the following:
public async ValueTask<string> Repeat(string message)
{
await using var jsModule = await moduleTask.Value;
var js = await jsModule!.InvokeAsync<IJSObjectReference>("GetInstance");
await js.InvokeVoidAsync("repeat", "Welcome");
}
Note that if your .ts file specifies a namespace (just like in C#), the path to the js method must include the namespace. So if your namespace is mycomp
, you should use mycomp.repeat
in the example above.
8. Implement your component
Edit your Component1.razor
file and add the following
<div class="component1">
What should I repeat: <input @bind="Message" />
<br/>
<button @onclick="Validate">Validate</button>
</div>
The component expects an input and will display that same input in an alert popup of the browser.
Create a Component1.razor.cs
file or append @code {}
to the html above to add the csharp logic. Here is how it would look like in a .cs file:
public partial class Component1 : IAsyncDisposable
{
private ComponentJsInterop interop;
[Inject]
public IJSRuntime JSRuntime { get; set; }
// Binding value
public string Message {get; set; } = "";
// Click handler
public async Task Validate()
{
await interop.Repeat(Message);
}
protected override void OnAfterRender(bool firstRender)
{
if(firstRender)
{
// On first rendering instantiate the interop
interop = new ComponentJsInterop(JSRuntime);
}
}
// Since interop is disposable, the component is disposable as well
public async ValueTask DisposeAsync()
{
if(interop != null)
{
await interop.DisposesAsync();
}
}
}
9. Use your component
In your MyComp.Tester.Client
project, add a project reference to MyComp
.
Now open the Counter
page and simply add :
<Component1 />
Run the app and you should now see your component which should work as expected.