Grand Masta1
Grand Masta1

Reputation: 837

Blazor onchange event with select dropdown

Note: this question was asked about a pre-release of Blazor (0.2.1).

So I have been stuck trying to get a simple onchange to fire when a select dropdown value changes. Like so:

<select class="form-control d-flex" onchange="(dostuff())">
    @foreach (var template in templatestate.templates)
    {
        <option [email protected]>@template.Name</option>
    }
</select>

               

with the method being called:

void dostuff()
{
   Console.WriteLine("first spot is firing");
    _template = templatestate.templates.FirstOrDefault(x => x.Name == 
    _template.Name);
    Console.WriteLine("second spot is firing");
}

The result I get it no matter how I try to reorient it is this error in the browser.

Uncaught Error: System.ArgumentException: There is no event handler with ID 0

Is there something obvious and key that I am missing? Because I have a button onclick event that works just fine on the same page.

Upvotes: 66

Views: 152153

Answers (7)

JhotaMS Developer
JhotaMS Developer

Reputation: 13

<div class="col-12 col-md-6 my-2">
<label class="font-weight-bold f-14">Clase de vehículo</label>

<InputSelect class="form-control form-select" id="vehicleClass" ValueChanged="@((string value) => References(value))"
              Value="@dtoSearchVehicleBy.VehicleClass" ValueExpression="@(() => dtoSearchVehicleBy.VehicleClass)">
    <option selected>Seleccionar</option>
    @foreach (var vehicle in vehicleByClass)
    {
        <option value="@vehicle.VehicleClass"> @vehicle.VehicleClass</option>
    }
</InputSelect>
<div class="text-danger">
    <ValidationMessage For="@(() => dtoSearchVehicleBy.VehicleClass)" />
</div>
        private void References(string value)
    {
        brand = dtoSearchVehicleBy.Brand;
        dtoSearchVehicleBy.VehicleClass = value;
        vehicleByBrandAndClass = vehicleByBrands.Where(x => x.Brand == brand && x.VehicleClass == value);
    }

Upvotes: 1

Linda Taylor
Linda Taylor

Reputation: 21

You can also try:

<select @onchange="(e => DoStuff(e.Value.ToString()))">

Upvotes: 2

Patrick Knott
Patrick Knott

Reputation: 1837

Your answer should be in the cshtml:

<select @onchange="DoStuff">  //pre-3.0 versions: onchange=@DoStuff
    @foreach (var template in templates)
    {
        <option value=@template>@template</option>
    }
</select>

Then your @functions (in razor components @code instead. See: Razor Syntax: Functions) should look like:

@functions {  //use @code in razor components.
    List<string> templates = new List<string>() { "Maui", "Hawaii", "Niihau", "Kauai", "Kahoolawe" };
    string SelectedString = "Maui";

    void DoStuff(ChangeEventArgs e)
    {
        SelectedString = e.Value.ToString();
        Console.WriteLine("It is definitely: " + SelectedString);
    }
}

You could also just use a bind...

<select @bind="SelectedString"> //pre 3.0 bind="@SelectedString"

but @onchange="DoStuff" allows you to perform logic on selection.

Here's a link to some changes: Blazor WebAssembly 3.2.0 Preview 5 release now available

Upvotes: 95

Amir Mahdi Nassiri
Amir Mahdi Nassiri

Reputation: 1330

Just wanted to add to the other answers that you can access the select value by using lambda expressions as well:

<select @onchange="@(e => ViewModel.TargetProperty = e.Value.ToString())">

In case you prefer to put your code right in the element.

Upvotes: 2

Rono
Rono

Reputation: 3381

As an alternative to setting an onchange event, you could just bind the dropdown to a property and handle changes in the property set. This way you get the value being selected all in the same process and without having to convert an object value. Plus if you're already using @bind on the select, you are prevented from using onchange on it as well.

<select @bind="BoundID">
 ...
</select>

@code {
  private int? _boundID = null;
  private int? BoundID
  {
    get
    {
      return _boundID;
    }
    set
    {
      _boundID = value;
     //run your process here to handle dropdown changes
    }
  }
}

Upvotes: 42

Pankaj Rawat
Pankaj Rawat

Reputation: 4583

Above answer didn't work for me, got compilation error.

below is my working code.

@inject HttpClient httpClient

@if (States != null)
{

<select id="SearchStateId" name="stateId" @onchange="DoStuff" class="form-control1">
    <option>@InitialText</option>
    @foreach (var state in States)
    {
        <option value="@state.Name">@state.Name</option>
    }
</select>
}


@code {
[Parameter] public string InitialText { get; set; } = "Select State";
private KeyValue[] States;
private string selectedString { get; set; }
protected override async Task OnInitializedAsync()
{
    States = await httpClient.GetJsonAsync<KeyValue[]>("/sample-data/State.json");
}

private void DoStuff(ChangeEventArgs e)
{
    selectedString = e.Value.ToString();
    Console.WriteLine("It is definitely: " + selectedString);
}

public class KeyValue
{
    public int Id { get; set; }

    public string Name { get; set; }
}
}

Upvotes: 11

Flores
Flores

Reputation: 8942

For starters you are not using the correct bind syntax:

onchange="@dostuff"

notice the @

Upvotes: 3

Related Questions