Marvin Klein
Marvin Klein

Reputation: 1746

How to use more controlled binding in blazor correctly?

I am trying to add more controlled binding to an InputSelect razor component. What I am trying to do is to execute the method LieferanschriftChangedAsync when the value of the property has changed. Here is my approach:

<InputSelect Value="Input.LieferanschriftId"
             ValueChanged="@((string s) => LieferanschriftChangedAsync(s))"
             ValueExpression="@(() => Input.LieferanschriftId)"
             class="form-control">
    <option value="0">--- Keine Lieferanschrift ---</option>
    @foreach (var anschrift in _lieferanschriften)
    {
        <option value="@anschrift.KULA_N_NR">@anschrift.ToString()</option>
    }
</InputSelect>
private Task LieferanschriftChangedAsync(string value)
{
    _ = int.TryParse(value, out int lieferanschriftId);

    Input.LieferanschriftId = lieferanschriftId;
    Input.Lieferanschrift = _lieferanschriften.Where(x => x.KULA_N_NR == lieferanschriftId).FirstOrDefault();

    return Task.CompletedTask;
}

I don't want to use the INotifyPropertyChanged interface for this because the model. However I always get an error message (CS0411) with this approach, which tells me to specify the datatype because it cannot be evaluated automatically. So I've added TValue="int" to my approach. Now I get the following error: Converting from "int" to "System.ReadOnlySpan" is not possible.

What am I doing wrong here? LieferanschriftId is an integer.

Upvotes: 0

Views: 156

Answers (2)

enet
enet

Reputation: 45586

Note: The proposed solution here is for .Net5.0. If you're using an earlier version of the framework, you should subclass the InputSelect component to enable support for integer or enum values...

Define the LieferanschriftId field in your model as nullable, like this:

[Required(ErrorMessage = "Please, select your...")]
public int? LieferanschriftId{ get; set; }

Now you can do:

<option value="">--- Keine Lieferanschrift ---</option>

You don't have a value == 0, right ? So why do value="0". Instead we resort to nullability, without which you can't ensure that your user has selected a value

This: ValueChanged="@((string s) => LieferanschriftChangedAsync(s))"

can be altered to: ValueChanged="@((int? args) => { Input.LieferanschriftId = args; })"

and you can discard of the LieferanschriftChangedAsync method altogether as executing this code is out of place:

Input.Lieferanschrift = _lieferanschriften.Where(x => x.KULA_N_NR == lieferanschriftId).FirstOrDefault();

Upvotes: 1

Kirk Woll
Kirk Woll

Reputation: 77536

The inferred type parameter (and also when you made it explicit) is int. This type parameter influences the ValueChanged event as well. Yet you've declared the event handler as expecting a string instead of an int. If you change it to (int s) (and change the parameter in LieferanschriftChangedAsync to also be an int, it should take care of your compiler issues. (Also, you wouldn't have to parse the value anymore since it's already an int).

Upvotes: 0

Related Questions