Directives are built-in macros that alter the transpiled C# code that is generated from Razor mark-up.
Directives are used by preceding the identifier with the @ symbol,
the identifier being what we'd typically expect to be either the name of an HTML attribute or the name of a component's property.
If you haven't done so already, read Literals, expressions, and directives.
Note: Currently, unlike other frameworks such as Angular, Blazor does not allow developers to create their own directives.
Because the type of the value assigned to the directive is known (it is strongly typed in C# code)
the value will be inferred to be an expression.
So, as with component properties, adding the @ at the start of assigned value is unnecessary unless we wish to pass an
expression to a directive that expects a string value.
An exception to this is when we wish to pass a lambda; lambdas must be escaped with an @ symbol and enclosed with brackets.
@onclick=@( args => Debug.WriteLine("Clicked") )
The following code shows how the @onclick directive is used to add the DOM onclick event to a rendered H1 element.
// Razor mark-up with @onclick directive
<h1 @onclick=H1Clicked>Hello, world!</h1>
@code
{
public void H1Clicked(MouseEventArgs args)
{
System.Diagnostics.Debug.WriteLine("H1 clicked");
}
}
// Transpiled C#
public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder __builder)
{
__builder.OpenElement(0, "h1");
__builder.AddAttribute(1, "onclick", EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.MouseEventArgs>(this, H1Clicked));
__builder.AddContent(2, "Hello, world!");
__builder.CloseElement();
}
}
- Line 2
Defines an H1 element with the@onclickdirective. - Line 18
Shows how the@onclick=H1Clickeddirective is transpiled so that the DOMonclickevent is set on the rendered element.
Some standard directives applicable to the Razor file itself are:
@code
This directive identifies a block of C# code that should be output as-is into the resulting C# file. It is possible to have multiple@codedirectives in a single Razor mark-up file; Blazor will collate these to a single block of C# code in the transpiled file.@page
This directive generates a[RouteAttribute]on the transpiled class, enabling Blazor routing (covered later) to identify which component (page) to render given a specific address in the URL.@layout
Generates a[LayoutAttribute]on the transpiled class. Blazor uses this to determine which Layout to use (if any) to wrap the contents of a page.@implements
Instructs Blazor to generate a class declaration that implements the specified interface.@inherits
Specifies a custom base class for the generated component class, instead of the defaultComponentBase.@typeparam
Instructs Blazor to generate a generic class from the Razor mark-up. We can also specify generic constraints using the standard C# syntax, for example@typeparam TItem where TItem : class.@namespace
Overrides the namespace generated for the component, which by default is derived from the folder path.@inject
Allows components to specify dependencies they require to be injected by Blazor when it creates a new instance of the component.@attribute
Adds the specified DotNet attribute to the generated C# class.@rendermode
Specifies the render mode for a component, such asInteractiveServer,InteractiveWebAssembly,InteractiveAuto, or a custom render mode. Components without an explicit@rendermodedefault to Static Server-Side Rendering (Static SSR).@preservewhitespace
Controls whether whitespace in the Razor source is preserved or trimmed in the rendered output. By default, leading and trailing whitespace is removed to minimise the render tree.
The following is a small set of examples of directives that can be applied to components and
HTML elements that the current Razor file is consuming.
For example <h1 @ref=MyH1Element>Hello</h1>.
@ref
Identifies a member or property of the current component that should hold a reference to an HTML element or component that will be rendered. These can be used as references when using JavaScript Interop, or to obtain a reference to an embedded Blazor component so that we can invoke methods on it.@bind
Allows us to data bind (Two way binding) to the property of a component being consumed, or the attribute of an HTML element. Additional directive attributes such as@bind:after,@bind:get, and@bind:setgive us finer control over binding behaviour.@bind:afterspecifies a callback that fires after the bound property is updated.@bind:getand@bind:setlet us separate the getter and setter for the bound value, enabling manual control of the update logic.@formname
Assigns a name to an HTML form element, which is required when using Blazor's enhanced form handling with static server-side rendering.@attributes
Outputs name-value pairs as HTML attributes.@key
Gives us the ability to give elements/components a unique identifier, which helps keep change deltas small when rendering to HTML.
And the following is a subset of HTML DOM element events that are available. These will be covered in more detail in Component events.
@onmousemove@onclick@onkeypress@onscroll
DOM event directives such as those above only function when the component has an interactive render mode assigned. Under Static Server-Side Rendering, these event handlers are not wired up. See the @rendermode entry above for details.
Directive attributes
Directive attributes allow us to pass additional information to directives. If we think of a directive as a class, then directive attributes are its members.
To pass this additional information we need to repeat the directive,
and then append a : followed by the name of the attribute that the directive supports.
For example, by default our browser will propagate an element's events up the tree until it finally reaches the HTML document itself. A plain HTML + JavaScript demonstration of this would be to output text to the console when an element is clicked.
<html>
<body>
<div onclick="console.log('Top level clicked')">
<h1>Top level</h1>
<div onclick="console.log('Second level clicked')">
<h2>Second level</h2>
<div onclick="console.log('Third level clicked')">
<h3>Third level</h3>
</div>
</div>
</div>
</body>
</html>
Because the div elements are nested,
when one of them is clicked that event will trigger not only the onclick code on the div itself,
but it will also trigger the onclick on its parent div,
which in turn will trigger then event on its own parent div - and so on, until the current element has no parent.

Console output when the Third level header is clicked
To prevent an event propagating up the element tree JavaScript has a
stopPropagation method on the event.
Blazor prevents propagation using a directive attribute - @onclick:stopPropagation.
@page "/"
@using System.Diagnostics
<div @onclick=TopLevelClicked>
<h1>Top level</h1>
<div @onclick=SecondLevelClicked @onclick:stopPropagation>
<h2>Second level</h2>
<div @onclick=ThirdLevelClicked>
<h3>Third level</h3>
</div>
</div>
</div>
@code
{
private void TopLevelClicked()
{
Debug.WriteLine("Top level clicked");
}
private void SecondLevelClicked()
{
Debug.WriteLine("Second level clicked");
}
private void ThirdLevelClicked()
{
Debug.WriteLine("Third level clicked");
}
}
Lines 4, 6, and 8 all define the @onclick attribute and
declare which C# method to execute when the Browser onclick event is triggered.
Line 6 adds an additional @onclick:stopPropagation to prevent the browser propagating
the click up from the second to the first level.
More DOM events will be covered in the section about DOM events.
Some directive attributes expect us to specify a value in the form @directive:attribute="value".
We'll cover this in detail in the section on Two-way binding.
