Home > Enterprise >  how to use InputNumber.ValueChanged?
how to use InputNumber.ValueChanged?

Time:09-09

I'm trying to use 2-way binding between a form and my object. I can get it to work for InputText. But i get this errors when i add the ValueChanged attribute for InputNumber:

CS1662 Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type

CS1503 Argument 2: cannot convert from 'method group' to 'EventCallback'

When i compile this Component.razor page:

@page "/test"

@using System.ComponentModel.DataAnnotations

<EditForm Model="@model">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <InputText Value="@model.Street" ValueExpression="@(() => model.Street)" ValueChanged="@StreetChanged" />
    <InputNumber Value="@model.HouseNr" ValueExpression="@(() => model.HouseNr)" ValueChanged="@HouseNrChanged" />
    <button type="submit">Send</button>
</EditForm>

@code {
    protected void StreetChanged(string? value)
    {
        // ... code to lookup address and fill other fields
        model.Street = value;
    }

    protected void HouseNrChanged(int? value)
    {
        // ... code to lookup address and fill other fields
        model.HouseNr = value;
    }

    private Address model { get; set; } = new();

    class Address
    { 
        [Required]
        public string? Street { get; set; }

        [Required]
        public int? HouseNr { get; set; }
    }
}

I've tried to changing my HouseNrChanged method, but i can't figure it out. It seems to have something to do with the different types of the ValueChanged properties:

  • InputText.ValueChanged has type EventCallback<string>
  • InputText.ValueChanged has type EventCallback<TValue>

Questions:

  • Any ideas on how to fix this?
  • Is there any documentation?
  • What does ValueExpression do besides causing a runtime error when it is omitted?

It's very hard to find examples

CodePudding user response:

It's because the type of the generic EventCallback<TValue> cannot be inferred. You have to set the TValue property on the InputNumber

<InputNumber TValue="int?" Value="@model.HouseNr" ValueExpression="@(() => model.HouseNr)" ValueChanged="@HouseNrChanged" />

CodePudding user response:

CS1503 Argument 2: cannot convert from 'method group' to 'EventCallback'

This is rather a generic error message which does not pinpoint the issue at hand. See this example this example

The following error message is where the issue is explained:

CS1662 Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type

To solve this issue you can either add the TValue attribute (TValue="int?") as suggested by Dimitris Maragkos, or still better, to my mind, as it makes the code clearer and more readable, use a lambda expression like this:

ValueChanged="(int? args) => HouseNrChanged(args)"

Now you can remember the role of the Value and ValueChanged attribute. They actually create a two-way data binding between the a model's property and an input type="" (in your case number) that is a constituent part of a component. This is how a two-way data binding is created between a variable and an input type="number"

<input type="number" value="@number" @onchange="(args) => 
                                    SelectYourNumber(args)" />

@code
{ 
   private int number = 10;

   protected void SelectYourNumber(ChangeEventArgs args)
   {
        var number = Convert.ToInt32(args.Value);
   }
}

Note that the value attribute's value in value="@number" must be preceded by the @ sign, while the Value attribute's value in
Value="@model.HouseNr" is rather optional, just for backwards compatibility. I'll never use Value="@model.HouseNr", but Value="model.HouseNr" Do you understand the difference ?

The best method to learn how things work is to consult the source code.

  • Related