Search code examples
c#asp.net-corevalidationrazor

Razor validation for multiple forms


My page is display a table with each row being a item from a list. Each row has a form to allow the user to update a value and submit it (and only it) back to the server. That is all working. However, I wish to add validation so that the number entered must be between 0 and another property of the row item. So I have the following:

    <tbody>
@foreach (var item in Model.ItemList) {
        <form method="post">
        <tr>
            <td>..</td>

            <td>
                <input type="hidden" asp-for="@item.Identifier" />
                <input asp-for="@item.PropertyToUpdate" class="form-control" min="0" max="@item.MaxValue"  id="@item.PropertyToUpdate" />
                
                <span asp-validation-for="@item.PropertyToUpdate" class="text-danger"></span>
            </td>
            <td>
                <input type="submit" value="Submit" class="btn btn-primary" />
            </td>
        </tr>
        </form>
}
    </tbody>

However, when the user enters the value and leaves the box, the validation message does not display.

Any ideas ?

Thanks in advance


Solution

  • You could try this below code to show the error message when user leaves the box:

    Index.cshtml:

    @page
    @model IndexModel
    @{
        ViewData["Title"] = "Item List";
    }
    
    <h2>Item List</h2>
    
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Property to Update</th>
                <th>Max Value</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.ItemList)
            {
                <form method="post" class="item-form">
                <tr>
                    <td>@item.Identifier</td>
                    <td>
                        <input type="hidden" asp-for="@item.Identifier" />
                        <input asp-for="@item.PropertyToUpdate"
                               class="form-control"
                               data-max-value="@item.MaxValue"
                               onblur="validateInput(this)" />
                        <span class="text-danger error-message" style="display:none;"></span>
                    </td>
                    <td>@item.MaxValue</td>
                    <td>
                        <input type="submit" value="Submit" class="btn btn-primary" />
                    </td>
                </tr>
                </form>
            }
        </tbody>
    </table>
    
    @section Scripts {
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    
        <script>
            function validateInput(input) {
                // Get the max value from the custom attribute
                const maxValue = parseInt($(input).attr("data-max-value"));
                const value = parseInt($(input).val());
    
                // Find the error message span
                const errorMessageSpan = $(input).siblings(".error-message");
    
                // Validate the input value
                if (isNaN(value) || value < 0 || value > maxValue) {
                    // Show error message if invalid
                    errorMessageSpan.text(`Please enter a value between 0 and ${maxValue}.`);
                    errorMessageSpan.show();
                } else {
                    // Hide error message if valid
                    errorMessageSpan.hide();
                }
            }
        </script>
    }
    

    Index.cshtml.cs:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using ValidationDemo.Models;
    
    namespace ValidationDemo.Pages
    {
        public class IndexModel : PageModel
        {
            [BindProperty]
            public List<Item> ItemList { get; set; }
    
            public void OnGet()
            {
                // Sample data for demonstration
                ItemList = new List<Item>
                {
                    new Item { Identifier = 1, MaxValue = 50, PropertyToUpdate = 10 },
                    new Item { Identifier = 2, MaxValue = 30, PropertyToUpdate = 5 },
                    new Item { Identifier = 3, MaxValue = 80, PropertyToUpdate = 20 },
                };
            }
    
            public IActionResult OnPost(int identifier, int propertyToUpdate)
            {
                // Process the form submission for the specific item
                var item = ItemList.Find(i => i.Identifier == identifier);
                if (item != null && propertyToUpdate >= 0 && propertyToUpdate <= item.MaxValue)
                {
                    item.PropertyToUpdate = propertyToUpdate;
                }
    
                return Page();
            }
    
    
        }
    }
    

    Item.cs:

    using System.ComponentModel.DataAnnotations;
    
    namespace ValidationDemo.Models
    {
        public class Item
        {
            public int Identifier { get; set; }
    
            [Range(0, 100, ErrorMessage = "MaxValue must be between 0 and 100.")]
            public int MaxValue { get; set; } // Max limit for PropertyToUpdate
    
            [Required(ErrorMessage = "Please enter a value.")]
            [Range(0, int.MaxValue, ErrorMessage = "Please enter a valid number between 0 and MaxValue.")]
            public int PropertyToUpdate { get; set; }
    
        }
    }
    

    enter image description here