Custom behavior in forms having a model with complex types collections

0 Answers 85 Views
DateInput Form
Max
Top achievements
Rank 1
Max asked on 12 Apr 2024, 03:59 PM

Hello,

I'm working on a .NET8 Blazor webapp with some InteractiveAutoRenderMode. I'm trying to figure out how to code the HTML/Razor in a Blazor component to be able to display a pair of inputs and then bind a collection of a complex type.
I also want the possibility for the user to add more instances to the collection within the UI/component by being able to add more inputs (through a button click) before submitting the form.

I am not sure how to capture the properties inside the complex type collection for the FieldIdentifier instance usually helping with binding and validation? And then how would that work within a loop for the user to be able to add more instances to the collection?

FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityStartTime)

 

The HTML for the pair of inputs looks like this:

ManageProductOffer.razor :

<div class="input-group">
    <label for="@($"""idAvailabilityStartInput""")">
        <input type="datetime-local" id="@($"""idAvailabilityStartInput""")" name="fAvailabilityStart"
                step="any" min="@(TimeProvider.GetLocalNow().LocalDateTime.ToString(SortableDateTimePatternFormat))"
                class="@(ApplyStyleForValidationState(FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities)))"
                value="@(NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityStartTime.ToString(SortableDateTimePatternFormat))"
                @onchange=@(changeEventArgs => TryBindAndValidateField(
                    changeEventArgs: changeEventArgs,
                    fieldIdentifier: FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityStartTime),
                    validationDelegate: () => LimitedAvailability.ValidateLimitedAvailability(NewProductOfferModel!.LimitedAvailabilities[0]))) />
    </label>

    <label for="@($"""idAvailabilityEndInput""")">
        <input type="datetime-local" id="@($"""idAvailabilityEndInput""")" name="fAvailabilityEnd"
                step="any" min="@(TimeProvider.GetLocalNow().LocalDateTime.ToString(SortableDateTimePatternFormat))"
                class="@(ApplyStyleForValidationState(FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities)))"
                value="@(NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityEndTime.ToString(SortableDateTimePatternFormat))"
                @onchange=@(changeEventArgs => TryBindAndValidateField(
                    changeEventArgs: changeEventArgs, 
                    fieldIdentifier: FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityEndTime),
                    validationDelegate: () => LimitedAvailability.ValidateLimitedAvailability(NewProductOfferModel!.LimitedAvailabilities[0]))) />
    </label>
    <small class="">
        <ValidationMessage For="@(() => NewProductOfferModel!.LimitedAvailabilities[0])" />
    </small>
</div>

 

And the code for the model with the complex type collection looks like this:

ProductOfferModel.cs :

public sealed record class ProductOfferModel
{
    public Guid ID { get; init; } = Guid.NewGuid();
    public String ProductOfferDescription { get; set; } = String.Empty;
    public Guid ProductID { get; set; } = Guid.Empty;
    public String ProductDescription { get; set; } = String.Empty;
    public List<LimitedAvailability> LimitedAvailabilities { get; set; } = [new LimitedAvailability()];
}

public sealed record class LimitedAvailability
{
    public Guid ID { get; init; } = Guid.NewGuid();
    public DateTime LimitedAvailabilityStartTime { get; set; } = DateTime.MinValue;
    public DateTime LimitedAvailabilityEndTime { get; set; } = DateTime.MinValue;

    internal static Boolean ValidateLimitedAvailability( LimitedAvailability limitedAvailability )
    {
        ArgumentNullException.ThrowIfNull(limitedAvailability);

        return limitedAvailability.LimitedAvailabilityStartTime < limitedAvailability.LimitedAvailabilityEndTime ?
            true
            : false;
    }
}

 

The (microsoft documentation) mentions supporting complex type and be able to nest and bind, however it does not seems to mention how to capture the FieldIdentifier accessor for a property inside complex type to customize @onchange or @oninput  behavior for example.

Anyone has been solving something similar with using collections of complex types and letting the user add more inputs to the form before submit?

No answers yet. Maybe you can help?

Tags
DateInput Form
Asked by
Max
Top achievements
Rank 1
Share this question
or