在第一个下拉菜单中选择一个值后,更改第二个下拉菜单项

时间:2020-09-16 02:45:43

标签: c# asp.net-mvc asp.net-core razor razor-pages

在ASP.NET Core Razor Pages的第一个下拉列表中选择了一个值时,我无法更新第二个下拉列表。

我有以下型号:

public class OfferModel
{
    [BindProperty]
    public CreateOfferViewModel ViewModel { get; set; }
    public List<SelectListItem> ServiceTypes { get; set; }
    public List<SelectListItem> ServiceSubTypes { get; set; }

    private readonly IOfferAppService _offerAppService;

    public OfferModel(IOfferAppService service)
    {
        _offerAppService = service;
    }

    public virtual async Task OnGetAsync()
    {
        var serviceTypeLookup = await _offerAppService.GetServiceTypeLookupAsync();
        ServiceTypes = serviceTypeLookup.Items
            .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
            .ToList();
        var serviceSubTypeLookup = await _offerAppService.GetServiceSubTypeLookupAsync();
        ServiceSubTypes = serviceSubTypeLookup.Items
            .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
            .ToList();
    }
}

和CreateOfferViewModel:

public class CreateOfferViewModel
{
    [SelectItems(nameof(ServiceTypes))]
    public Guid ServiceTypeId { get; set; }

    [SelectItems(nameof(ServiceSubTypes))]
    public Guid ServiceSubTypeId { get; set; }
}

视图:

<select asp-for="ViewModel.ServiceSubTypeId" asp-items="Model.ServiceSubTypes"></select>
<select asp-for="ViewModel.ServiceTypeId" asp-items="Model.ServiceTypes" ></select>

我尝试创建另一个类似的方法:

public virtual async Task OnGetSelectServiceTypeAsync(Guid serviceTypeId)
    {
        var serviceSubTypeLookup = await _offerAppService.GetServiceSubTypeLookupAsync(serviceTypeId);
        ServiceSubTypes = serviceSubTypeLookup.Items
                        .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
                        .ToList();
    }

并在视图中添加引用以使用jQuery进行调用:

<a asp-page-handler="SelectServiceType" asp-route-id="@Model.ViewModel.ServiceTypeId">Update</a>

但是我得到了NullReferenceException。

我该怎么办?正确的方法是什么?

1 个答案:

答案 0 :(得分:1)

但是我得到了NullReferenceException。

这是因为您使用了asp-route-id="@Model.ViewModel.ServiceTypeId",但没有为其设置任何值。

有两种方法可以满足您的要求。

型号:

public class CreateOfferViewModel
{
    public Guid ServiceTypeId { get; set; }
    public Guid ServiceSubTypeId { get; set; }
}
public class ServiceSubTypes
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    [ForeignKey("ServiceTypes")]
    public Guid ServiceTypeId { get; set; }
    public ServiceTypes ServiceTypes { get; set; }
}
public class ServiceTypes
{
    public Guid Id { get; set; }
    public string Name { get; set; }
   
    public List<ServiceSubTypes> ServiceSubTypes { get; set; }
}

第一种方法是使用Ajax:

Index.cshtml:

@page
@model IndexModel
<select asp-for="ViewModel.ServiceTypeId" asp-items="Model.ServiceTypes"></select>

<select asp-for="ViewModel.ServiceSubTypeId"></select>

@section Scripts
{
    <script>
        $(function () {
            $("#ViewModel_ServiceTypeId").on("change", function () {
                var ServiceTypeId = $(this).val();
                $("#ViewModel_ServiceSubTypeId").empty();
                $.getJSON(`?handler=SelectServiceType&serviceTypeId=${ServiceTypeId}`, (data) => {
                    $.each(data, function (i, item) {
                        console.log(data);
                        console.log(item);
                        $("#ViewModel_ServiceSubTypeId").append(`<option value="${item.id}">${item.name}</option>`);
                    });
                });
            });
        });

    </script>
}

Index.cshtml.cs:

public class IndexModel : PageModel
{
    [BindProperty]
    public CreateOfferViewModel ViewModel { get; set; }
    public List<SelectListItem> ServiceTypes { get; set; }
    public List<SelectListItem> ServiceSubTypes { get; set; }

    private readonly IOfferAppService _offerAppService;

    public IndexModel(IOfferAppService service)
    {
        _offerAppService = service;
    }

    public virtual async Task OnGetAsync()
    {
        var serviceTypeLookup = await _offerAppService.GetServiceTypeLookupAsync();
        ServiceTypes = serviceTypeLookup
            .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
            .ToList();
        var serviceSubTypeLookup = await _offerAppService.GetServiceSubTypeLookupAsync();
        ServiceSubTypes = serviceSubTypeLookup
            .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
            .ToList();
    }
    public virtual async Task<JsonResult> OnGetSelectServiceTypeAsync(Guid serviceTypeId)
    {
        var serviceSubTypeLookup = await _offerAppService.GetServiceSubTypeLookupAsync(serviceTypeId);
        
        return new JsonResult(serviceSubTypeLookup);
    }
}

服务:

public interface IOfferAppService
{
    Task<List<ServiceTypes>> GetServiceTypeLookupAsync();
    Task<List<ServiceSubTypes>> GetServiceSubTypeLookupAsync();
    Task<List<ServiceSubTypes>> GetServiceSubTypeLookupAsync(Guid id);
}
public class OfferApp : IOfferAppService
{
    private readonly RazorProj3_1Context _context;
    public OfferApp(RazorProj3_1Context context)
    {
        _context = context;
    }
    public async Task<List<ServiceSubTypes>> GetServiceSubTypeLookupAsync()
    {
        var model =await _context.ServiceSubTypes.ToListAsync();
        return model;
    }

    public async Task<List<ServiceSubTypes>> GetServiceSubTypeLookupAsync(Guid id)
    {
        var model = await _context.ServiceSubTypes
                    .Where(a => a.ServiceTypeId == id).ToListAsync();
        return model;
    }

    public async Task<List<ServiceTypes>> GetServiceTypeLookupAsync()
    {
        var model = await _context.ServiceTypes.ToListAsync();
        return model;
    }
}

结果: enter image description here

第二种方法类似于您要使用jquery将值添加到url的方法,但是这种方法有一个缺点,它将在浏览器地址栏中显示URL:

Index.cshtml:

@page
@model IndexModel
<select asp-for="ViewModel.ServiceTypeId" asp-items="Model.ServiceTypes"></select>
<select asp-for="ViewModel.ServiceSubTypeId" asp-items="Model.ServiceSubTypes"></select>

<a href="">Update</a>

@section Scripts
{
    <script>
        $(function () {
            $("#ViewModel_ServiceTypeId").on("change", function () {
                var ServiceTypeId = $(this).val();
                var url = $("a").attr("href", "?handler=SelectServiceType&serviceTypeId=" + ServiceTypeId);
            });
        });

    </script>
}

Index.cshtml.cs:

public class IndexModel : PageModel
{
    [BindProperty]
    public CreateOfferViewModel ViewModel { get; set; }
    public List<SelectListItem> ServiceTypes { get; set; }
    public List<SelectListItem> ServiceSubTypes { get; set; }

    private readonly IOfferAppService _offerAppService;

    public IndexModel(IOfferAppService service)
    {
        _offerAppService = service;
    }

    public virtual async Task OnGetSelectServiceTypeAsync(Guid serviceTypeId)
    {
        var serviceTypeLookup = await _offerAppService.GetServiceTypeLookupAsync();
        ServiceTypes = serviceTypeLookup
            .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
            .ToList();
        //obtain the first select item selected
        var data = ServiceTypes.Where(a => a.Value == serviceTypeId.ToString()).FirstOrDefault();
        data.Selected = true;
        var serviceSubTypeLookup = await _offerAppService.GetServiceSubTypeLookupAsync(serviceTypeId);
        ServiceSubTypes = serviceSubTypeLookup
                        .Select(x => new SelectListItem(x.Name, x.Id.ToString()))
                        .ToList();
        
    }
}

结果: enter image description here