{"id":53498,"date":"2020-07-21T08:00:17","date_gmt":"2020-07-21T06:00:17","guid":{"rendered":"https:\/\/code-maze.com\/?p=53498"},"modified":"2022-05-22T14:52:08","modified_gmt":"2022-05-22T12:52:08","slug":"blazor-webassembly-forms-form-validation","status":"publish","type":"post","link":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/","title":{"rendered":"Blazor WebAssembly Forms, Form Validation, and @ref Directive"},"content":{"rendered":"<p>Sending a GET request to the server-side application and showing the data on the page is just a part of any application. In addition to that, we have to create our data and send POST requests as well. While creating forms, we have to provide validation for a user on that form.<\/p>\n<p>So, creating Blazor WebAssembly forms and their validation is going to be the topic of this article. Additionally, we are going to learn how to use the modal window as a component to display a success message after the create action finishes successfully.<\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">To download the source code for this article, you can visit the <a href=\"https:\/\/github.com\/CodeMazeBlog\/blazor-series\/tree\/blazor-webassembly-forms\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Blazor WebAssembly Forms and Validation repository<\/a>.<\/div>\n<p>For the complete navigation for this series, you can visit the <a href=\"https:\/\/code-maze.com\/blazor-webassembly-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">Blazor Series page<\/a>.<\/p>\n<p>Let&#8217;s start.<\/p>\n<h2 id=\"post-action-web-api\">Handling the POST action on the Web API\u2019s Side<\/h2>\n<p>For our application to work, we need to have a server-side implementation for the POST action. Of course, this will be a basic implementation because this series is not about the Web API logic, it is about the Blazor WebAssembly. So, if you want to learn in great detail about handling POST actions in Web API, we strongly recommend reading <a href=\"https:\/\/code-maze.com\/net-core-web-development-part6\/\" target=\"_blank\" rel=\"noopener noreferrer\">our article on that topic<\/a>.<\/p>\n<div style=\"padding: 20px; border-left: 5px lightgray solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">Additionally, you can visit our <a href=\"https:\/\/code-maze.com\/net-core-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">entire Web API series<\/a>, to expand your knowledge about the entire process of Web API creation.<\/div>\n<p>That said, let\u2019s start with the interface modification:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"4\">public interface IProductRepository\r\n{\r\n    Task&lt;PagedList&lt;Product&gt;&gt; GetProducts(ProductParameters productParameters);\r\n    Task CreateProduct(Product product);\r\n}\r\n<\/pre>\n<p>Then, we have to implement this method in the repository class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public async Task CreateProduct(Product product)\r\n{\r\n    _context.Add(product);\r\n    await _context.SaveChangesAsync();\r\n}\r\n<\/pre>\n<p>Finally, we have to add a <code>Create<\/code> action in the <code>ProductController<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[HttpPost]\r\npublic async Task&lt;IActionResult&gt; CreateProduct([FromBody] Product product)\r\n{\r\n    if (product == null)\r\n        return BadRequest();\r\n   \r\n   \/\/model validation\u2026\r\n\r\n    await _repo.CreateProduct(product);\r\n\r\n    return Created(\"\", product);\r\n}\r\n<\/pre>\n<p>And that\u2019s all it takes.<\/p>\n<p>We can send the POST request from Postman:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/46-Create-Postman-Request.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-53499\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/46-Create-Postman-Request.png\" alt=\"Create Postman Request\" width=\"638\" height=\"487\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/46-Create-Postman-Request.png 638w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/46-Create-Postman-Request-300x229.png 300w\" sizes=\"auto, (max-width: 638px) 100vw, 638px\" \/><\/a><\/p>\n<p>And we can confirm that a new product has been created. Of course, you can check the database as well.<\/p>\n<h2 id=\"post-blazor\">Preparing the POST Request on the Blazor WebAssembly Side<\/h2>\n<p>Now that we have prepared the server-side logic, we can continue with the client-side. The first thing we are going to do is to modify the <code>IProductHttpRepository<\/code> interface:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"4\">public interface IProductHttpRepository\r\n{\r\n    Task&lt;PagingResponse&lt;Product&gt;&gt; GetProducts(ProductParameters productParameters);\r\n    Task CreateProduct(Product product);\r\n}\r\n<\/pre>\n<p>Then, let\u2019s modify the <code>ProductHttpRepository<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public async Task CreateProduct(Product product)\r\n{\r\n    var content = JsonSerializer.Serialize(product);\r\n    var bodyContent = new StringContent(content, Encoding.UTF8, \"application\/json\");\r\n\r\n    var postResult = await _client.PostAsync(\"products\", bodyContent);\r\n    var postContent = await postResult.Content.ReadAsStringAsync();\r\n\r\n    if(!postResult.IsSuccessStatusCode)\r\n    {\r\n        throw new ApplicationException(postContent);\r\n    }\r\n}\r\n<\/pre>\n<p>In this method, we serialize our product object and create a new body content with the <code>StringContent<\/code> class. Then, we just use the <code>PostAsync<\/code> method to send the POST request to the server-side application. Additionally, we extract the content from the response. If the response is unsuccessful, we just throw an exception with the postContent variable as a parameter.<\/p>\n<h2 id=\"forms\">Creating Blazor WebAssembly Forms<\/h2>\n<p>We should be able to navigate to the Product creation page and for that, let\u2019s create it in the <code>Pages<\/code> folder:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/47-Create-product-component-structure.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-53500\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/47-Create-product-component-structure.png\" alt=\"Create product component structure for Blazor WebAssembly Forms\" width=\"219\" height=\"125\" \/><\/a><\/p>\n<p>Now, let\u2019s modify the class file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public partial class CreateProduct\r\n{\r\n    private Product _product = new Product();\r\n\r\n    private void Create()\r\n    {\r\n            \r\n    }\r\n}<\/pre>\n<p>Here, we have a private <code>_product<\/code> variable that we are going to use to bind our values from the form input fields. Also, we have a single <code>Create<\/code> method to execute when we click the <code>Submit<\/code> button on the form. We are going to leave it empty for now.<\/p>\n<p>After the class modification, let\u2019s create our form in the <code>CreateProduct<\/code> razor file. <strong>If you are using .NET 6 and above, just use <\/strong><code>mb-3<\/code><strong> class instead of the <\/strong><code>form-group<\/code><strong> to keep everything in order<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">@page \"\/createProduct\"\r\n\r\n&lt;h2&gt;Create Product Form&lt;\/h2&gt;\r\n\r\n&lt;EditForm Model=\"_product\" OnSubmit=\"Create\" class=\"card card-body bg-light mt-5\"&gt;\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"name\" class=\"col-md-2 col-form-label\"&gt;Name:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputText id=\"name\" class=\"form-control\" @bind-Value=\"_product.Name\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"supplier\" class=\"col-md-2 col-form-label\"&gt;Supplier:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputText id=\"supplier\" class=\"form-control\" @bind-Value=\"_product.Supplier\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"price\" class=\"col-md-2 col-form-label\"&gt;Price:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputNumber id=\"price\" class=\"form-control\" @bind-Value=\"_product.Price\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"image\" class=\"col-md-2 col-form-label\"&gt;Image:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputText id=\"image\" class=\"form-control\" @bind-Value=\"_product.ImageUrl\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"row\"&gt;\r\n        &lt;div class=\"col-md-12 text-right\"&gt;\r\n            &lt;button type=\"submit\" class=\"btn btn-success\"&gt;Create&lt;\/button&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/EditForm&gt;\r\n<\/pre>\n<p>In this file, we create a route with the <code>@page<\/code> directive and then our form elements. We use the <code>EditForm<\/code> component to create our form and this component accepts the <code>Model<\/code> parameter and the <code>OnSubmit<\/code> event callback. For the <code>Model<\/code> parameter, we pass our <code>_product<\/code> object, and for the <code>OnSubmit<\/code> event emitter, we provide our <code>Create<\/code> method. Then, we have a familiar code with bootstrap classes, <code>InputText<\/code> and <code>InputNumber<\/code> components. These components help us working with the forms by providing additional styles for valid and invalid controls. Furthermore, Blazor provides us with additional Input components for different input types (InputCheckBox, InputDate, InputSelect\u2026).<\/p>\n<p>Of course, later on in the series, we are going to replace the input text control for the ImageUrl property and implement a file upload functionality for that control.<\/p>\n<h3>Calling the Repository Method and Testing the Creation Action<\/h3>\n<p>So, now we have to modify our <code>CreateProduct<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"5,6,10\">public partial class CreateProduct\r\n{\r\n    private Product _product = new Product();\r\n\r\n    [Inject]\r\n    public IProductHttpRepository ProductRepo { get; set; }\r\n\r\n    private async Task Create()\r\n    {\r\n        await ProductRepo.CreateProduct(_product);\r\n    }\r\n}\r\n<\/pre>\n<p>And that\u2019s it. All we have to do is to inject our product repository service and call the <code>CreateProduct<\/code> method in the <code>Create<\/code> method.<\/p>\n<p>Now, we can test the solution:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/48-Create-form-test.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-53501\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/48-Create-form-test.png\" alt=\"Create From - Blazor WebAssembly Forms\" width=\"1032\" height=\"306\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/48-Create-form-test.png 1032w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/48-Create-form-test-300x89.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/48-Create-form-test-1024x304.png 1024w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/48-Create-form-test-768x228.png 768w\" sizes=\"auto, (max-width: 1032px) 100vw, 1032px\" \/><\/a><\/p>\n<p>After we click the create button, we can inspect the product page and we are going to find our new product for sure.<\/p>\n<p>Excellent. But far from over.<\/p>\n<p>We need to implement validation for our form and we have to notify the user about the successfully create action. So, let\u2019s continue.<\/p>\n<h2 id=\"validation\">Blazor WebAssembly Forms Validation<\/h2>\n<p>To start with the validation process, we have to install the <code>System.ComponentModel.Annotations<\/code> library in the <code>Entities<\/code> project:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/50-Annotations-package-installed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-53503\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/50-Annotations-package-installed.png\" alt=\"Annotations package installed\" width=\"720\" height=\"161\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/50-Annotations-package-installed.png 720w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/50-Annotations-package-installed-300x67.png 300w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/a><\/p>\n<p><code>PM&gt; Install-Package System.ComponentModel.Annotations<\/code><\/p>\n<p>After that, we have to modify the <code>Product.cs<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"4,6,8\">public class Product\r\n{\r\n    public Guid Id { get; set; }\r\n    [Required(ErrorMessage = \"Name is required field\")]\r\n    public string Name { get; set; }\r\n    [Required(ErrorMessage = \"Supplier is required field\")]\r\n    public string Supplier { get; set; }\r\n    [Range(1, double.MaxValue, ErrorMessage = \"Value for the Price can't be lower than 1\")]\r\n    public double Price { get; set; }\r\n    public string ImageUrl { get; set; }\r\n}\r\n<\/pre>\n<p>Here, we require the <code>Name<\/code> and the <code>Supplier<\/code> properties to be populated and we don\u2019t allow the price to be less than 1.<\/p>\n<p>Finally, we have to modify the <code>CreateProduct<\/code> razor file to add the validation components:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\" data-enlighter-highlight=\"1,2,7,15,23\">&lt;EditForm Model=\"_product\" OnValidSubmit=\"Create\" class=\"card card-body bg-light mt-5\"&gt;\r\n    &lt;DataAnnotationsValidator \/&gt;\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"name\" class=\"col-md-2 col-form-label\"&gt;Name:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputText id=\"name\" class=\"form-control\" @bind-Value=\"_product.Name\" \/&gt;\r\n            &lt;ValidationMessage For=\"@(() =&gt; _product.Name)\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"supplier\" class=\"col-md-2 col-form-label\"&gt;Supplier:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputText id=\"supplier\" class=\"form-control\" @bind-Value=\"_product.Supplier\" \/&gt;\r\n            &lt;ValidationMessage For=\"@(() =&gt; _product.Supplier)\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"price\" class=\"col-md-2 col-form-label\"&gt;Price:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputNumber id=\"price\" class=\"form-control\" @bind-Value=\"_product.Price\" \/&gt;\r\n            &lt;ValidationMessage For=\"@(() =&gt; _product.Price)\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"form-group row\"&gt;\r\n        &lt;label for=\"image\" class=\"col-md-2 col-form-label\"&gt;Image:&lt;\/label&gt;\r\n        &lt;div class=\"col-md-10\"&gt;\r\n            &lt;InputText id=\"image\" class=\"form-control\" @bind-Value=\"_product.ImageUrl\" \/&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n\r\n    &lt;div class=\"row\"&gt;\r\n        &lt;div class=\"col-md-12 text-right\"&gt;\r\n            &lt;button type=\"submit\" class=\"btn btn-success\"&gt;Create&lt;\/button&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/EditForm&gt;\r\n<\/pre>\n<p>We can see that we change the <code>OnSubmit<\/code> event emitter to the <code>OnValidSubmit<\/code> event emitter. With this, our form will send the request \u2013 once we click the submit button \u2013 only if it&#8217;s valid. Then, we add the <code>DataAnnotationsValidator<\/code> component to help our form understand the rules from the <code>Product.cs<\/code> class. Finally, we use the <code>ValidationMessage<\/code> component to show the error message for each input field.<\/p>\n<p>Now, if we try to create a product with invalid data:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/51-Invalid-form.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-53504\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/51-Invalid-form.png\" alt=\" Invalid form\" width=\"1037\" height=\"460\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/51-Invalid-form.png 1037w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/51-Invalid-form-300x133.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/51-Invalid-form-1024x454.png 1024w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/51-Invalid-form-768x341.png 768w\" sizes=\"auto, (max-width: 1037px) 100vw, 1037px\" \/><\/a><\/p>\n<p>We can see the errors on the screen, and our request is not sent.<\/p>\n<p>One more thing. We are only showing the error messages next to the validated inputs. But, we can show the error summary as well by using the <code>&lt;ValidationSummary \/&gt;<\/code> component. If you want to use it, just place it right below the <code>&lt;DataAnnotationsValidator \/&gt;<\/code> component.<\/p>\n<div style=\"padding: 20px; border-left: 5px lightgray solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">To read even more about the Form validation in Blazor, you can read our <a href=\"https:\/\/code-maze.com\/custom-validation-in-blazor-webassembly\/\" target=\"_blank\" rel=\"noopener\">Custom Validation in Blazor WebAssembly<\/a> article, and also the <a href=\"https:\/\/code-maze.com\/complex-model-validation-in-blazor\/\" target=\"_blank\" rel=\"noopener\">Complex Model Validation in Blazor<\/a>. <\/div>\n<h2 id=\"bootstrap-modal\">Using Bootstrap Modal for Notifications and @ref Directive<\/h2>\n<p>After this implementation, we can finally create a notification component for our <code>CreateProduct<\/code> component. To do that, we are going to create the <code>SuccessNotification.razor<\/code> and <code>.cs<\/code> files in the <code>Shared<\/code> folder.<\/p>\n<p>Then, let\u2019s modify the razor file first:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;div class=\"modal @_modalClass\" tabindex=\"-1\" role=\"dialog\" style=\"display:@_modalDisplay\"&gt;\r\n    &lt;div class=\"modal-dialog\" role=\"document\"&gt;\r\n        &lt;div class=\"modal-content\"&gt;\r\n            &lt;div class=\"modal-header\"&gt;\r\n                &lt;h5 class=\"modal-title\"&gt;Success&lt;\/h5&gt;\r\n                &lt;button type=\"button\" class=\"close\" @onclick=\"Hide\" aria-label=\"Close\"&gt;\r\n                    &lt;span aria-hidden=\"true\"&gt;&amp;times;&lt;\/span&gt;\r\n                &lt;\/button&gt;\r\n            &lt;\/div&gt;\r\n            &lt;div class=\"modal-body\"&gt;\r\n                &lt;p&gt;Action completed successfully.&lt;\/p&gt;\r\n            &lt;\/div&gt;\r\n            &lt;div class=\"modal-footer\"&gt;\r\n                &lt;button type=\"button\" class=\"btn btn-success\" data-dismiss=\"modal\" @onclick=\"Hide\"&gt;Close&lt;\/button&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n\r\n@if (_showBackdrop)\r\n{\r\n    &lt;div class=\"modal-backdrop fade show\"&gt;&lt;\/div&gt;\r\n}\r\n<\/pre>\n<p>This is a simple bootstrap code for showing a modal window. Now, we need to create these variables and methods in the class file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public partial class SuccessNotification\r\n{\r\n    private string _modalDisplay;\r\n    private string _modalClass;\r\n    private bool _showBackdrop;\r\n\r\n    [Inject]\r\n    public NavigationManager Navigation { get; set; }\r\n\r\n    public void Show()\r\n    {\r\n        _modalDisplay = \"block;\";\r\n        _modalClass = \"show\";\r\n        _showBackdrop = true;\r\n        StateHasChanged();\r\n    }\r\n\r\n    private void Hide()\r\n    {\r\n        _modalDisplay = \"none;\";\r\n        _modalClass = \"\";\r\n        _showBackdrop = false;\r\n        StateHasChanged();\r\n        Navigation.NavigateTo(\"\/products\");\r\n    }\r\n}<\/pre>\n<p>So, in both methods, we give a value to each of our variables and additionally call the <code>StateHasChanged<\/code> method. This method notifies a component that the state has changed and forces it to re-render. Additionally, we have injected the <code>NavigationManager<\/code> service and used it to navigate to the products page.<\/p>\n<p>Now, let\u2019s add this component to the <code>CreateProduct<\/code> component:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">&lt;SuccessNotification @ref=\"_notification\"\/&gt;<\/code><\/p>\n<p>We can see the <code>@ref<\/code> directive. This directive enables using the members from the child component inside the parent component. Because we want to show this notification inside the <code>CreateProduct<\/code> component, we are going to use the <code>_notification<\/code> variable to call the <code>Show<\/code> method which resides in the <code>SuccessNotification<\/code> component.<\/p>\n<p>Finally, we have to modify the <code>CreateProduct<\/code> class file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"4,12\">public partial class CreateProduct\r\n{\r\n    private Product _product = new Product();\r\n    private SuccessNotification _notification;\r\n\r\n    [Inject]\r\n    public IProductHttpRepository ProductRepo { get; set; }\r\n\r\n    private async Task Create()\r\n    {\r\n        await ProductRepo.CreateProduct(_product);\r\n        _notification.Show();\r\n    }\r\n}\r\n<\/pre>\n<p>In here, we just create the <code>_notification<\/code> variable of type <code>SuccessNotification<\/code> and use it inside the <code>Create<\/code> method to show the notification.<\/p>\n<p>Now, as soon as we create a new product, we are going to see a modal window with the success message:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/52-modal-success.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-53505\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/52-modal-success.png\" alt=\"Success modal window in Blazor WebAssembly Forms\" width=\"730\" height=\"368\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/52-modal-success.png 730w, https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/52-modal-success-300x151.png 300w\" sizes=\"auto, (max-width: 730px) 100vw, 730px\" \/><\/a><\/p>\n<p>And once we click the Ok button, we are going to be redirected to the <code>Products<\/code> page.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>So, we have learned many different things in this article. From creating the POST request on the server-side and client-side to creating and validating the Blazor WebAssembly forms. Additionally, we have seen how to use the @ref directive to call the members from the child component.<\/p>\n<p>In the next article, we are going to replace the image URL text box with the upload component and will learn <a href=\"https:\/\/code-maze.com\/blazor-webassembly-file-upload\/\" target=\"_blank\" rel=\"noopener noreferrer\">how to upload files in Blazor WebAssembly<\/a>.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sending a GET request to the server-side application and showing the data on the page is just a part of any application. In addition to that, we have to create our data and send POST requests as well. While creating forms, we have to provide validation for a user on that form. So, creating Blazor [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":55054,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[683,684,12],"tags":[685,686,726,727,144],"class_list":["post-53498","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blazor","category-blazor-webassembly","category-csharp","tag-blazor","tag-blazor-webassembly","tag-blazor-webassembly-forms","tag-forms-validation","tag-modal-windows","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Blazor WebAssembly Forms, Form Validation, and @ref Directive<\/title>\n<meta name=\"description\" content=\"In this article, we are going to learn about Blazor WebAssembly Forms creation and how to create and validate a form for the POST actions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Blazor WebAssembly Forms, Form Validation, and @ref Directive\" \/>\n<meta property=\"og:description\" content=\"In this article, we are going to learn about Blazor WebAssembly Forms creation and how to create and validate a form for the POST actions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2020-07-21T06:00:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-05-22T12:52:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Marinko Spasojevi\u0107\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Marinko Spasojevi\u0107\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\"},\"author\":{\"name\":\"Marinko Spasojevi\u0107\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\"},\"headline\":\"Blazor WebAssembly Forms, Form Validation, and @ref Directive\",\"datePublished\":\"2020-07-21T06:00:17+00:00\",\"dateModified\":\"2022-05-22T12:52:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\"},\"wordCount\":1264,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png\",\"keywords\":[\"Blazor\",\"Blazor WebAssembly\",\"Blazor WebAssembly Forms\",\"Forms Validation\",\"Modal windows\"],\"articleSection\":[\"Blazor\",\"Blazor WebAssembly\",\"C#\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\",\"url\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\",\"name\":\"Blazor WebAssembly Forms, Form Validation, and @ref Directive\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png\",\"datePublished\":\"2020-07-21T06:00:17+00:00\",\"dateModified\":\"2022-05-22T12:52:08+00:00\",\"description\":\"In this article, we are going to learn about Blazor WebAssembly Forms creation and how to create and validate a form for the POST actions.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png\",\"width\":1100,\"height\":620,\"caption\":\"09 Forms, Form Validation, and @ref Directive\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blazor WebAssembly Forms, Form Validation, and @ref Directive\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\",\"name\":\"Marinko Spasojevi\u0107\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"caption\":\"Marinko Spasojevi\u0107\"},\"description\":\"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/marinko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Blazor WebAssembly Forms, Form Validation, and @ref Directive","description":"In this article, we are going to learn about Blazor WebAssembly Forms creation and how to create and validate a form for the POST actions.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/","og_locale":"en_US","og_type":"article","og_title":"Blazor WebAssembly Forms, Form Validation, and @ref Directive","og_description":"In this article, we are going to learn about Blazor WebAssembly Forms creation and how to create and validate a form for the POST actions.","og_url":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/","og_site_name":"Code Maze","article_published_time":"2020-07-21T06:00:17+00:00","article_modified_time":"2022-05-22T12:52:08+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png","type":"image\/png"}],"author":"Marinko Spasojevi\u0107","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Marinko Spasojevi\u0107","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/"},"author":{"name":"Marinko Spasojevi\u0107","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533"},"headline":"Blazor WebAssembly Forms, Form Validation, and @ref Directive","datePublished":"2020-07-21T06:00:17+00:00","dateModified":"2022-05-22T12:52:08+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/"},"wordCount":1264,"commentCount":4,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png","keywords":["Blazor","Blazor WebAssembly","Blazor WebAssembly Forms","Forms Validation","Modal windows"],"articleSection":["Blazor","Blazor WebAssembly","C#"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/","url":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/","name":"Blazor WebAssembly Forms, Form Validation, and @ref Directive","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png","datePublished":"2020-07-21T06:00:17+00:00","dateModified":"2022-05-22T12:52:08+00:00","description":"In this article, we are going to learn about Blazor WebAssembly Forms creation and how to create and validate a form for the POST actions.","breadcrumb":{"@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/09-Forms-Form-Validation-and-@ref-Directive.png","width":1100,"height":620,"caption":"09 Forms, Form Validation, and @ref Directive"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/blazor-webassembly-forms-form-validation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Blazor WebAssembly Forms, Form Validation, and @ref Directive"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533","name":"Marinko Spasojevi\u0107","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","caption":"Marinko Spasojevi\u0107"},"description":"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.","sameAs":["https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/marinko\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/53498","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=53498"}],"version-history":[{"count":4,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/53498\/revisions"}],"predecessor-version":[{"id":70477,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/53498\/revisions\/70477"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/55054"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=53498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=53498"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=53498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}