Blazor Inputselect onchange 事件不起作用
Blazor Inputselect onchange event doesnot work
我在这里使用 blazor 服务器应用程序,并尝试使用 @onchange="countyClicked"
事件根据国家/地区下拉列表的变化填充城市下拉列表,并将下拉列表与模型绑定。
现在问题是 onchange 事件不起作用,并且城市下拉列表不会在国家/地区下拉列表的 onchange 中填充。
下面是我的组件 html for dropdownlist
<InputSelect @bind-Value="PersonModel.CountryId" class="form-control" @onchange="countyClicked">
<option value="">Select country</option>
@foreach (var item in Countries)
{
<option value="@item.CountryId">@item.CountryName</option>
}
</InputSelect>
<InputSelect class="form-control mb-2 mr-sm-2" @bind-Value="PersonModel.CityId">
@foreach (var city in Cities)
{
<option value="@city.CityId">@city.CityName</option>
}
</InputSelect>
<br><br>
public void countyClicked(ChangeEventArgs args)
{
var getCountryId = args.Value.ToString();
int.TryParse(getCountryId, out int countryId);
Cities = mainService.GetAllCityByCountryId(countryId);
}
更改您的 editform,改为使用您的模型的 editcontext。
<EditForm EditContext="EditContext">
@*You don't have to write a onchange becuase your EditContext_OnFieldChanged will catch your changes*@
<InputSelect @bind-Value="PersonModel.CountryId" class="form-control">
<option value="">Select country</option>
@foreach (var item in Countries)
{
<option value="@item.CountryId">@item.CountryName</option>
}
</InputSelect>
<InputSelect class="form-control mb-2 mr-sm-2" @bind-Value="PersonModel.CityId">
@foreach (var city in Cities)
{
<option value="@city.CityId">@city.CityName</option>
}
</InputSelect>
</<EditForm >
有了它,您可以使用 OnFieldChanged 事件订阅在表单中所做的任何模型更改。
private EditContext EditContext;
private YourModel PersonModel= new YourModel();
protected override void OnInitialized()
{
//Don't forget to assign a value to your PersonModel!
EditContext = new EditContext(PersonModel);
EditContext.OnFieldChanged += EditContext_OnFieldChanged;
}
private void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
{
// identify field, retreive the set value from the model and populate the cities collection
}
注意:@onchange
是与 Html 元素一起使用的编译器指令。它不适用于 Razor 组件。但是,InputSelect 组件在内部使用 change
事件。
以下代码示例演示了您应该如何填充两个 InputSelect 组件、它们如何相互交互以及它们如何与表单的其余部分交互。另请注意,我使用验证强制用户 select 一个国家,然后是一个城市,否则无法“提交”表单。
将代码复制到您的索引页面并进行测试。
Index.razor
@page "/"
@using System.ComponentModel.DataAnnotations;
<EditForm EditContext="@EditContext" OnValidSubmit="HandleValidSubmit"
Context="NewContext">
<DataAnnotationsValidator />
<div class="form-group">
<label for="name">Enter your Name: </label>
<InputText Id="name" Class="form-control" @bind-Value="@person.Name">
</InputText>
<ValidationMessage For="@(() => person.Name)" />
</div>
<div class="form-group">
<label for="body">Select your country: </label>
<InputSelect ValueExpression="@(() => person.CountryID)"
Value="@person.CountryID"
ValueChanged="@((int? args) => { person.CountryID = args; SelectCities(args); })">
<option value="">Select country...</option>
@foreach (var country in countryList)
{
<option value="@country.ID">@country.Name</option>
}
</InputSelect>
<ValidationMessage For="@(() => person.CountryID)" />
</div>
@if (cityList != null && cityList.Any())
{
<div class="form-group">
<label for="body">Select your city: </label>
<InputSelect ValueExpression="@(() => person.CityID)"
Value="@person.CityID" ValueChanged="@((int? args) =>
person.CityID = args)">
<option value="">Select city...</option>
@foreach (var city in cityList)
{
<option value="@city.ID">@city.Name</option>
}
</InputSelect>
<ValidationMessage For="@(() => person.CityID)" />
</div>
}
<p>
<button type="submit">Submit</button>
</p>
</EditForm>
@code
{
private EditContext EditContext;
private Person person = new Person() { };
private List<Country> countryList = new List<Country>
{
new Country
{
ID = 1, Name="USA",
Cities = new List<City> { new City { ID = 1, Name = "City1" },
new City { ID = 2, Name = "City2" } }
},
new Country
{
ID =2, Name="Germany",
Cities = new List<City> { new City { ID = 3, Name = "City3" },
new City { ID = 4, Name = "City4" } }
},
new Country {ID =3, Name="France",
Cities = new List<City> { new City { ID = 5, Name = "City5" },
new City { ID =6, Name = "City6" } } },
new Country {ID =4, Name="UK",
Cities = new List<City> {
new City { ID = 7, Name = "City7" },
new City { ID =8, Name = "City8" },
new City { ID = 9, Name = "City9" },
new City { ID = 10, Name = "City10" }} },
new Country {ID =5, Name="Russia",
Cities = new List<City> { new City { ID = 11, Name = "City11" } }}
};
private IQueryable<City> cityList;
private void HandleValidSubmit()
{
Console.WriteLine("Submitting");
}
protected override void OnInitialized()
{
EditContext = new EditContext(person);
base.OnInitialized();
}
private void SelectCities(int? id)
{
person.CityID = null;
cityList = (from country in countryList
where country.ID == id
from city in country.Cities
select city).AsQueryable();
}
public class Country
{
public int ID { get; set; }
public string Name { get; set; }
public List<City> Cities { get; set; }
}
public class City
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Person
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required(ErrorMessage ="Please, select your country.")]
public int? CountryID { get; set; }
[Required(ErrorMessage = "Please, select your city.")]
public int? CityID { get; set; }
}
}
更新:
ValueChanged="@((int? args) => { person.CountryID = args; SelectCities(args); })" do
ValueChanged is defined in the InputSelect component's class as an EventCallback. When you select an item in the select element, the `change` event is triggered. In JavaScript you can access the newly selected value through the event object. In Blazor (JSInterop is behind the scene), you code is passed the selected value in the parameter args (int? args), and your code should assign it to the bound filed (person.CountryID). This is equivalent to what you were trying to do by using `@onchange="countyClicked"`, which is correct when you use html element, but the InputSelect is a component, not html element.
SelectCities(args)
是在Country InputSelect中select取值时调用的方法,其参数为selected值;即selected国家的id;其作用是根据国家/地区过滤城市 selected.
阅读问题和我的回答
阅读我的回答 here
看我的回答 and
我在这里使用 blazor 服务器应用程序,并尝试使用 @onchange="countyClicked"
事件根据国家/地区下拉列表的变化填充城市下拉列表,并将下拉列表与模型绑定。
现在问题是 onchange 事件不起作用,并且城市下拉列表不会在国家/地区下拉列表的 onchange 中填充。
下面是我的组件 html for dropdownlist
<InputSelect @bind-Value="PersonModel.CountryId" class="form-control" @onchange="countyClicked">
<option value="">Select country</option>
@foreach (var item in Countries)
{
<option value="@item.CountryId">@item.CountryName</option>
}
</InputSelect>
<InputSelect class="form-control mb-2 mr-sm-2" @bind-Value="PersonModel.CityId">
@foreach (var city in Cities)
{
<option value="@city.CityId">@city.CityName</option>
}
</InputSelect>
<br><br>
public void countyClicked(ChangeEventArgs args)
{
var getCountryId = args.Value.ToString();
int.TryParse(getCountryId, out int countryId);
Cities = mainService.GetAllCityByCountryId(countryId);
}
更改您的 editform,改为使用您的模型的 editcontext。
<EditForm EditContext="EditContext">
@*You don't have to write a onchange becuase your EditContext_OnFieldChanged will catch your changes*@
<InputSelect @bind-Value="PersonModel.CountryId" class="form-control">
<option value="">Select country</option>
@foreach (var item in Countries)
{
<option value="@item.CountryId">@item.CountryName</option>
}
</InputSelect>
<InputSelect class="form-control mb-2 mr-sm-2" @bind-Value="PersonModel.CityId">
@foreach (var city in Cities)
{
<option value="@city.CityId">@city.CityName</option>
}
</InputSelect>
</<EditForm >
有了它,您可以使用 OnFieldChanged 事件订阅在表单中所做的任何模型更改。
private EditContext EditContext;
private YourModel PersonModel= new YourModel();
protected override void OnInitialized()
{
//Don't forget to assign a value to your PersonModel!
EditContext = new EditContext(PersonModel);
EditContext.OnFieldChanged += EditContext_OnFieldChanged;
}
private void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
{
// identify field, retreive the set value from the model and populate the cities collection
}
注意:@onchange
是与 Html 元素一起使用的编译器指令。它不适用于 Razor 组件。但是,InputSelect 组件在内部使用 change
事件。
以下代码示例演示了您应该如何填充两个 InputSelect 组件、它们如何相互交互以及它们如何与表单的其余部分交互。另请注意,我使用验证强制用户 select 一个国家,然后是一个城市,否则无法“提交”表单。 将代码复制到您的索引页面并进行测试。
Index.razor
@page "/"
@using System.ComponentModel.DataAnnotations;
<EditForm EditContext="@EditContext" OnValidSubmit="HandleValidSubmit"
Context="NewContext">
<DataAnnotationsValidator />
<div class="form-group">
<label for="name">Enter your Name: </label>
<InputText Id="name" Class="form-control" @bind-Value="@person.Name">
</InputText>
<ValidationMessage For="@(() => person.Name)" />
</div>
<div class="form-group">
<label for="body">Select your country: </label>
<InputSelect ValueExpression="@(() => person.CountryID)"
Value="@person.CountryID"
ValueChanged="@((int? args) => { person.CountryID = args; SelectCities(args); })">
<option value="">Select country...</option>
@foreach (var country in countryList)
{
<option value="@country.ID">@country.Name</option>
}
</InputSelect>
<ValidationMessage For="@(() => person.CountryID)" />
</div>
@if (cityList != null && cityList.Any())
{
<div class="form-group">
<label for="body">Select your city: </label>
<InputSelect ValueExpression="@(() => person.CityID)"
Value="@person.CityID" ValueChanged="@((int? args) =>
person.CityID = args)">
<option value="">Select city...</option>
@foreach (var city in cityList)
{
<option value="@city.ID">@city.Name</option>
}
</InputSelect>
<ValidationMessage For="@(() => person.CityID)" />
</div>
}
<p>
<button type="submit">Submit</button>
</p>
</EditForm>
@code
{
private EditContext EditContext;
private Person person = new Person() { };
private List<Country> countryList = new List<Country>
{
new Country
{
ID = 1, Name="USA",
Cities = new List<City> { new City { ID = 1, Name = "City1" },
new City { ID = 2, Name = "City2" } }
},
new Country
{
ID =2, Name="Germany",
Cities = new List<City> { new City { ID = 3, Name = "City3" },
new City { ID = 4, Name = "City4" } }
},
new Country {ID =3, Name="France",
Cities = new List<City> { new City { ID = 5, Name = "City5" },
new City { ID =6, Name = "City6" } } },
new Country {ID =4, Name="UK",
Cities = new List<City> {
new City { ID = 7, Name = "City7" },
new City { ID =8, Name = "City8" },
new City { ID = 9, Name = "City9" },
new City { ID = 10, Name = "City10" }} },
new Country {ID =5, Name="Russia",
Cities = new List<City> { new City { ID = 11, Name = "City11" } }}
};
private IQueryable<City> cityList;
private void HandleValidSubmit()
{
Console.WriteLine("Submitting");
}
protected override void OnInitialized()
{
EditContext = new EditContext(person);
base.OnInitialized();
}
private void SelectCities(int? id)
{
person.CityID = null;
cityList = (from country in countryList
where country.ID == id
from city in country.Cities
select city).AsQueryable();
}
public class Country
{
public int ID { get; set; }
public string Name { get; set; }
public List<City> Cities { get; set; }
}
public class City
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Person
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required(ErrorMessage ="Please, select your country.")]
public int? CountryID { get; set; }
[Required(ErrorMessage = "Please, select your city.")]
public int? CityID { get; set; }
}
}
更新:
ValueChanged="@((int? args) => { person.CountryID = args; SelectCities(args); })" do
ValueChanged is defined in the InputSelect component's class as an EventCallback. When you select an item in the select element, the `change` event is triggered. In JavaScript you can access the newly selected value through the event object. In Blazor (JSInterop is behind the scene), you code is passed the selected value in the parameter args (int? args), and your code should assign it to the bound filed (person.CountryID). This is equivalent to what you were trying to do by using `@onchange="countyClicked"`, which is correct when you use html element, but the InputSelect is a component, not html element.
SelectCities(args)
是在Country InputSelect中select取值时调用的方法,其参数为selected值;即selected国家的id;其作用是根据国家/地区过滤城市 selected.
阅读问题