This chapter will get you started with Blazor. As mentioned in the previous chapter, all three types of Blazor have a lot in common. Before we can go any further, we will need to look at the syntax and see how it works. Then we will get into the essentials of Blazor, such as bindings and method execution; all of these topics will be used later in the book.
In this chapter, you will learn about the following:
Differences Between Razor and Blazor
Simplistically speaking, the difference between Razor and Blazor is that Razor will be executed once on page launch, while the Blazor functionality will work all the time. In other words, the loops and logic statements
will get re-evaluated in Blazor, while with Razor it will happen only once.
Syntax
As mentioned previously
, if you know Razor syntax, you will know Blazor syntax. However, if you do not know Razor syntax, this is the section for you. The Blazor code goes into a markup file named .razor, which contains HTML as well as C# code.
Comments
Even
though
we use HTML syntax in a Blazor file, we do not use HTML comments. Instead, we use
Razor syntax
and get a beautiful and efficient commenting system, with no comments left on a generated page. Listing
2-1 illustrates this.
@*
Below is a test p element
*@
Listing 2-1Razor/Blazor Comment Syntax
As shown in Listing 2-1, you simply start a comment section with @* and then end with *@. You can also use the standard HTML comments, but using the Razor/Blazor syntax will be easier to see in the code. The Razor/Blazor comment syntax
characters get highlighted, and the actual comment is displayed in green. The comments will not be visible in published app using browser developer tools.
Sections
Razor syntax
is basically C# and HTML code in one file, and while they do interact, you need some higher contrast between the two languages. That is where all the different sections come in; as you will see, the sections are C# dominant, and they are used to highlight the C# parts of the code.
In Listing
2-2, a variable is being
declared
, and then it is displayed directly in a paragraph using C# code. So, for a single variable and the construction of classes, you can simply use the
@ sign and write everything on a single line. If you want to write more than one line for a variable declaration, you need to create a section using
@{ ... }.
@{
string teststring = “tst”;
}
<p>@teststring</p>
Listing 2-2Basic Blazor Sections
At this point, this may look very simple, so let’s dive into a few more examples.
In Listing
2-3, the
testint variable is declared and set to the value 0, followed by an
if statement checking if the value of
testint is not 0. Since the
statement criteria
is not satisfied, whatever is inside the
if statement is not displayed. If the
testint variable is set to any other value than 0, say 1, the HTML paragraph tag and value would be displayed. The C# code in the
@{ } section is highlighted, and it requires no
@ sign for each line. The
if statement part starts with the
@ sign and creates a section similar to the previous example. This means the HTML
code
in the
if statement section is not highlighted in any way.
@if (testint != 0)
{
<p>Is not equal to zero</p>
}
Listing 2-3if Statement Syntax
In Listing
2-4, a
for loop
has been created, looping five times. Each loop creates a new paragraph tag containing the value for the current iteration,
i. The
for loop part is highlighted in a slight shade of gray, while the
@ signs are highlighted in yellow. The HTML part
inside
the loop is not highlighted, but the C# code is; that is how you can tell the difference between HTML markup and C# code.
@for (int i = 0; I < 5; i++)
{
<p>@i</p>
}
Listing 2-4Syntax Coloring
Finally, there’s the code section (see Listing
2-5) where all the methods should be declared. The
binding variables
should also be added to the code section, which you will
find
later in this chapter (in the “Blazor Binds” section).
<p>test</p>
@code {
int a;
double b = 2.5;
void testmethod() {
}
}
Blazor Binds
Blazor allows you to bind an HTML input value to a variable and vice versa. Therefore, for the most part, we can call all bindings two-way. If you bind a text box (input type text) to a string variable, the displayed value will be the value of that string. Different elements will work differently, and there are many use cases for this.
Binding to an Element
Binding to an element
is simple. Not all elements can be bound, but most can.
Elements where values can be bound to a variable are as follows:
The listed elements are the most common elements that can be bound, but most others will work in some way.
In Listing
2-6, two simple
variables
have been declared, and initial have been values assigned. Listing
2-7 shows how to bind them to different elements.
@code {
string teststring = "test value";
bool testbool = true;
}
<input type="checkbox" @bind="@testbool">
<input @bind="@teststring">
<textarea @bind="@teststring"></textarea>
In Listing 2-7, a Boolean value
is bound to a check box, checked/unchecked, and the same is true for a radio button. The string value can be bound to any text value such as input, textarea, and others. When the input value changes, the variable value changes, and when the variable value changes, the value displayed in the input tag will change too.
The previous option can be considered
a default option to do the binding; however, there are additional parameters that you can use.
In Listing
2-8, you can see a binding on a specific event, rather than the default one. In this particular example, you can see that the
oninput event is specified, and when it occurs, the input text will go into the
displaytext string. This is useful, because it gets displayed right away, rather than the
onchange event, which requires for the input to lose focus for it to occur. This example is most common, and most other event/HTML tag combinations likely will not work.
<p><input type="text" @bind:event="oninput" @bind="displaytext" /></p>
<p>@displaytext</p>
@code {
string displaytext = "";
}
Listing 2-8Bind on Specific Event
In general, the value that you bind needs to be present
in the event arguments for the event specified.
Events
The code
section
is where the C# methods for the front end are added. The code sections are meant to contain your code for the client side, variables, and methods. It is much like a
<script> tag in a standard HTML page, but there’s more to it, as shown in Listing
2-9.
<p>@testvar</p>
@code {
string testvar = "test variable";
}
Listing 2-9Variable Display
In Listing
2-9, a variable is declared, and then it is added to a paragraph tag. This is quite special, as shown in Listing
2-10.
<p>@testvar</p>
<p><button @onclick="@testmethod">change</button></p>
@code {
string testvar = "test variable";
void testmethod() {
testvar = "test";
}
}
Listing 2-10Onclick Event
In Listing
2-10, the same
variable
as in Listing
2-9 is declared and then displayed in the paragraph tag. There’s also a C# method, which, in clientside Blazor, will run on the front end. The method is called by declaring it in the
onclick event
attribute for the button tag, but parentheses should not be used. The method simply changes the value for the variable, and in turn what is displayed in the paragraph tag is also changed. So, that is a
oneway binding
, and in Listing
2-11, a
two-way binding
is shown.
<p>@testvar</p>
<p><input @bind="@testvar"></p>
<p><button @onclick="@(() => testmethod())">change</button></p>
@code {
string testvar = "nothing to display";
void testmethod()
{
testvar = "test value";
}
}
Listing 2-11Bind, Onclick, and Display
In Listing 2-11, an input tag
is bound to the testvar variable
, so whenever the input tag value changes, the variable will also change, and therefore the display in the paragraph tag also changes. Do note that the input tag must lose focus for it to take effect.
So, that is how to call a method accepting no parameters. While it is not recommended, Listing
2-12 shows how to pass and accept parameters. Your method could also be a
Task method
, and you would be able to await it in that
lambda expression
.
<p>@testvar</p>
<p><input @bind="@testvar"></p>
<p><button @onclick="@( () => testmethod("test var"))">change</button></p>
@code {
string testvar = "nothing to display";
void testmethod(string testparam)
{
testvar = testparam;
}
}
Listing 2-12Method with Parameters
In Listing 2-12, the method accepts the testparam parameter
. So, use parentheses on the method call, and pass the value to call the method, rather than declaring it for the event almost like a variable. Use a lambda expression, and then use the method normally. This can be useful if different values are needed in the list output
. To use a Task method
, a lambda expression
should be used as well.
As shown in Listing
2-13, it is quite easy to do, but it is recommended to use the
await keyword and use a
Task with an
async method.
<p>@testvar</p>
<p><input @bind="@testvar" /></p>
<p><button @onclick="@(async () => await testmethod())">change</button></p>
@code {
string testvar = "nothing to display";
async Task testmethod()
{
testvar = "test value";
}
}
Listing 2-13Asynchronous Task
Finally, you are not limited to one method; there is also an option to execute several methods in each event and/or simply set variables directly in the event.
In Listing
2-14, you can see how a
Boolean variable
is set to true when the button is clicked, without the use of an additional method. In that area, you could also execute additional methods or use
if statements and other logic. If you want to use
await, you will simply need to add the
async keyword like you saw in the previous example. This option can make your code look cleaner in the code section, but it should not be abused as it might make the HTML part a lot less readable.
<p><button @onclick="@(() => { buttonclicked = true; })">Click button</button></p>
@code {
bool buttonclicked = false;
Listing 2-14Direct Use of Event
Event Arguments
Each event has its own argument
; for example, the input contains the input text. In a way, this is how bindings work; you just do not have to access the arguments directly. But there are cases where you need to, so here is how to do it.
In Listing
2-15, you can see the
oninput event
being used and the argument from that assigned to the
testvar string. To retrieve an argument, you simply set a name in the setup for the event. This variable in this case is an object (it can be converted to a string, but for numerics you can use
double,
int, or something else).
<p>@testvar</p>
<p><input @oninput="@((args) => { testvar = args.Value.ToString(); })" /></p>
@code {
string testvar = "";
Listing 2-15Event Overrides
It is important to note that the arguments
for the events in Blazor and in JavaScript are not always the same.
Page and Component Lifecycle Events
Whenever the user loads
a page (or a component), some events are triggered. These can be used to invoke your procedures on various stages of a page/component cycle.
The first and likely most common event is
OnInitializedAsync (Listing
2-16)
. This event occurs before the page gets rendered. If you have to pull data and display it without user input, this is where such procedures should go.
@page "/"
<h1>Index page</h1>
@code {
protected override Task OnInitializedAsync()
{
return base.OnInitializedAsync();
}
}
Listing 2-16Event Overrides
After the page gets rendered, the
OnAfterRenderAsync event
occurs (Listing
2-17). This can be used for procedures that require UI elements to be fully loaded.
protected override Task OnAfterRenderAsync(bool firstRender)
{
return base.OnAfterRenderAsync(firstRender);
}
Listing 2-17Event Overrides
This event will also recur if there are any updates to the page or if StateHasChanged() has been invoked
(covered later in the book). Therefore, if you want to use it only on the initial render, you can check if the Boolean value is true.
Finally,
OnParametersSetAsync (Listing
2-18) will occur when a new parameter is set. You will learn more about
parameters
later in the book; this event mostly applies to components.
protected override Task OnParametersSetAsync()
{
return base.OnParametersSetAsync();
}
Listing 2-18Event Overrides
Summary
You now know some basics of Blazor, as well as the most important parts of it: bindings and method executions. In the next chapters, we will dive deeper into Blazor and explore the differences between the different types. With that, we will not forget the basics, and you will see something from this chapter occurring in almost every example of code in this book.