9

Hello i have 2 variables of type int that i would like to bind to the min and max values of an input of type time.
How can i do this?

I do not know what to place in the bind field since there are 2 different variables. Also there is the min and max attributes.

<input type="time" min="@model.min" max="@model.max" bind=?/>

What should i put in the bind ?

Update On a more thoroughly analysis i decided i will need 2 variables of type Timespan and i will bind these to 2 inputs of type time.

2
  • Do you have a field in your model for the time? Commented Feb 25, 2019 at 15:15
  • I have 2 fields of type Timespan and i need to somehow limit the user to an interval [ from hour - to Hour] ...e.g [ 13.00 17.00] Commented Feb 25, 2019 at 15:31

6 Answers 6

8

.NET 6.0.8 now has nice functionality for this in InputDate, that supports the TimeOnly type (among others). I found out as i was studying the .NET source code and about to create my own (due to ccStars' answer)

<InputDate Type="InputDateType.Time" @bind-Value="@model.TimeVar" />

Where TimeVar has type TimeOnly?. It's nice that it handles nullable types.

1
  • I like to note, that if you try to "misuse" this for a timespan-control, you will have Problems in the US with the 12h-Format. AM/PM will be attached to your text.
    – Hunv
    Commented Sep 14, 2022 at 20:09
7

Previous solution was not working for me with .net Core 3.1 so I'll add an updated one:

Use Blazor :

<EditForm Model=@model OnValidSubmit="Submit">
    <InputText type="time" @bind-Value="TimeProxy" />
</EditForm>

Code changes are necessary as well.

@code {
    // This field is required as you can not use property in out statement
    private TimeSpan LocalTime = TimeSpan.FromHours(0);
    private string TimeProxy { 
        get => model.Time.ToString();
        set => TimeSpan.TryParse(value,out LocalTime);
    }
    private void Submit() {
        model.Time = LocalTime;
        // following submit logic...
    }
}
6

You cannot bind a TimeSpan directly to an input in Blazor, but you can use a property to convert it to/from a string.

<input type="time" min="@model.min" max="@model.max" bind="@TimeProxy" />

and

@functions
{
  string TimeProxy { get => model.Time.ToString(); set => TimeSpan.TryParse(value,out model.Time); }
}
1
  • 1
    This is not working on Blazor net5.0 Commented Feb 23, 2022 at 12:42
2

You can also do the following:

<input type="time" @bind="SomeTime" @bind:format="HH:mm"/>

@code {
    public DateTime SomeTime = new DateTime();

    private TimeSpan _time = SomeTime.TimeOfDay;
}

Please not this doesn't bind to the TimeSpan directly!

1

I wrote a little component for this which utilizes databinding and works with the proper data types.

usage:

<LabeledTime @bind-Value="shutdownDelay"></LabeledTime>

component:

<label class="form-label" for="@LabelId">
    @ChildContent
</label>
<input id="@LabelId" type="time" value="@ValueInternal.ToString("hh\\:mm")" step="60" @onchange="InternalValueChanged"/>

@code {

    private long LabelId = DateTime.Now.Ticks;

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter]
    public TimeSpan Value { get; set; }

    [Parameter]
    public EventCallback<TimeSpan> ValueChanged { get; set; }

    private TimeSpan ValueInternal { get; set; }

    protected override void OnParametersSet()
    {
        ValueInternal = Value;
        base.OnParametersSet();
    }

    private void InternalValueChanged(ChangeEventArgs obj)
    {
        if (!TimeSpan.TryParseExact(obj.Value.ToString(), "hh\\:mm\\:ss", null, out var result))
            return;

        ValueInternal = result;
        Value = result;
        ValueChanged.InvokeAsync(result);
    }
}
1
  • I used this and modified it to work with the new .net 6 TimeOnly type. Worked great thank you. Commented Aug 4, 2021 at 0:14
1

Hopefully this helps, I was also trying to bind a Timespan a input of type="time" I managed to achieve it with the help from the following site https://www.meziantou.net/creating-a-inputselect-component-for-enumerations-in-blazor.htm

This is the code I created to achieve this
InputTime.cs

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Rendering;
using System;
using System.Globalization;

namespace Example
{
    public sealed class InputTime : InputBase<TimeSpan>
    {
        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {    
            builder.OpenElement(0, "input");
            builder.AddAttribute(1, "type", "time");
            builder.AddMultipleAttributes(2, AdditionalAttributes);
            builder.AddAttribute(3, "class", CssClass);
            builder.AddAttribute(4, "value", BindConverter.FormatValue(CurrentValueAsString));
            builder.AddAttribute(5, "onchange", EventCallback.Factory.CreateBinder<string>(this, value => CurrentValueAsString = value, CurrentValueAsString, null));
            builder.CloseElement(); // close the select element
        }
               
        protected override bool TryParseValueFromString(string value, out TimeSpan result, out string validationErrorMessage)
        {        
            validationErrorMessage = null;
            return BindConverter.TryConvertTo<TimeSpan>(value, CultureInfo.CurrentCulture, out result);
        }
    }
}

Razor Page

<div class="form-group">
    <label>Time From</label>
    <InputTime @bind-Value="MyModel.TimeFrom" class="form-control"></InputTime>
    <ValidationMessage For="() => MyModel.TimeFrom"></ValidationMessage>
</div>
2
  • nice component!
    – symbiont
    Commented Aug 26, 2022 at 9:45
  • no more need for a custom component. TimeOnly is now directly supported by InputDate with (see my answer)
    – symbiont
    Commented Sep 6, 2022 at 15:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.