'How can I use Html.EditorFor() inside a razor component?

I have as ASP.NET Core/.net 5 based project. I want to create some sort of reusable view/component for creating a datetime range selector. So anytime I want to create datetime range can just call the view/component and it'll render the view accordingly.

My initial thought want to create an Editor Template for the following model

public class DateTimeRange
{
    public DateTime? From { get; set; }

    public DateTime? To { get; set; }
}

Then any time I want to render a datetime range, I would then do something like this

public class MainViewModel
{
     public DateTimeRange Range { get; set; }
}

and in the Main.cshtml view I would do something like this

@model MainViewModel

@Html.EditorFor(x => x.Range)

But in the above use case, there is no way to tell the editor if the range should be required or not.

So I thought about using razor components since components allow me to pass parameters to the view

The DateTime.razor component would look something like this


@if (IsRequired)
{
    <div class="col p-1">
        <label class="sr-only" asp-for=""></label>
        <input type="text" class="form-control" asp-for="" required>
    </div>


    <div class="col p-1">
        <label class="sr-only" asp-for=""></label>
        <input type="text" class="form-control" asp-for="" required>
    </div>
}
else
{

    <div class="col p-1">
        <label class="sr-only" asp-for=""></label>
        <input type="text" class="form-control" asp-for="">
    </div>


    <div class="col p-1">
        <label class="sr-only" asp-for=""></label>
        <input type="text" class="form-control" asp-for="">
    </div>
}

@code {

    public bool IsRequired { get; set; }
}

Then in my main view I would do something like this

@model MainViewModel

<component type="typeof(DateTime)" param-IsRequired="true" param-Model="Model.Range" />

But, how would I use asp-for helper or any other to render the input for the From and To Properties from inside the component while not losing the integrity of the HTML-prefix?



Solution 1:[1]

I Write a simply demo to show how to use asp-for in View Component:

Models/DateTimeRange

public class DateTimeRange
    {
       //Add validation
        [Required]
        public DateTime? From { get; set; }
        [Required]
        public DateTime? To { get; set; }
    }

Models/DateTimeRange

public class MainViewModel
    {
        public DateTimeRange Range { get; set; }
    }

Components/RangeViewConponent.cs

 public class RangeViewComponent : ViewComponent
        {            
            public async Task<IViewComponentResult> InvokeAsync()
            {          
                return View();
            }            
        }

Views/shared/Components/Range/default.cshtml

@model ComponentTest.Models.MainViewModel

<form method="post" asp-controller="Home" asp-action="privacy">
    <div class="col p-1">
        <label class="sr-only" asp-for="@Model.Range.From"></label>
        <input type="date" class="form-control" asp-for="@Model.Range.From" >
        <span asp-validation-for="@Model.Range.From" class="text-danger"></span>
    </div>

    <div class="col p-1">
        <label class="sr-only" asp-for="@Model.Range.To"></label>
        <input type="date" class="form-control" asp-for="@Model.Range.To" >
        <span asp-validation-for="@Model.Range.To" class="text-danger"></span>
    </div>
    <button type="submit">submit</button>
</form>

I use View Component in HomeController/Privacy

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

//use View Component
@await Component.InvokeAsync("Range")

//Add validation javascript
@section Scripts{
   <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
   <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
}

You can see if I don't select any date and click submit button, the error message will show and I can't submit any data

enter image description here

Then I select the date and click the submit button , the View Component can submit the MainViewModel successfully

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Xinran Shen