【问题标题】:Change second dropdown items after selecting a value in the first one在第一个中选择一个值后更改第二个下拉项
【发布时间】:2021-01-02 20:00:02
【问题描述】:

当在 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。

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

【问题讨论】:

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


    【解决方案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>
    }
    

    索引.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;
        }
    }
    

    结果:

    第二种方式就像你想用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>
    }
    

    索引.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();
            
        }
    }
    

    结果:

    【讨论】:

    • 太完美了,非常感谢!你已经付出了很多努力,请允许我请你喝咖啡或啤酒
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多