代码之家  ›  专栏  ›  技术社区  ›  Dev

如何在mudselect中使用ValueChanged

  •  0
  • Dev  · 技术社区  · 1 年前

    我正试图写一个为MudSelect下拉菜单编写通用组件。组件的选项是从父级传递的,当选定的选项更改时,我想获得在选项中定义的值,该选项是一个类,并导航到定义的页面。

    以下是代码

    HomePage.razor
    
     <HomeContainerComponent>
         <div>
             <HomeDropdownComponent Options="@dropdownOptions" TValue="string" SelectedOption="@selectedOption" OnValueChanged="OnValueChanged" SelectedOptionChanged="SelectedOptionChanged"></HomeDropdownComponent>
         </div>
    </<HomeContainerComponent>
    
    HomePage.razor.cs
    using Microsoft.AspNetCore.Components;
     
    
    namespace Test.Shared.Components.Pages
    {
        public partial class HomePage :ComponentBase
        {
            
            [Inject] private NavigationManager? NavigationManager { get; set; }
            protected List<DropdownOptions<string>> dropdownOptions { get; set; } = new();      
            public DropdownOptions<string> selectedOption { get; set; } = new();       
            protected  override void OnInitialized()
            {
                dropdownOptions = FetchDropdownOptions();
                selectedOption = dropdownOptions?.FirstOrDefault() ?? new();
            }
            private List<DropdownOptions<string>> FetchDropdownOptions()
            {
              return  dropdownOptions = new List<DropdownOptions<string>>
                {
                    new DropdownOptions<string> { Value = "Option1", Text = "Option1" ,ImageUrl ="_content/Test.Shared.Components/option1.png"},
                    new DropdownOptions<string> { Value = "Option2", Text = "Option2" ,ImageUrl ="_content/Test.Shared.Components/option2.png"},
                    new DropdownOptions<string> { Value = "Option3", Text = "Option3" ,ImageUrl ="_content/Test.Shared.Components/option3.png" , PageName = "/mud-tab"},
                    new DropdownOptions<string> { Value = "Option4", Text = "Option4" ,ImageUrl ="_content/Test.Shared.Components/option3.png"},
                };
            }
            private void OnValueChanged(string selected)
            {
                selectedOption = dropdownOptions?.Where( x => x.Text == selected).FirstOrDefault() ?? new();
                NavigationManager?.NavigateTo(selectedOption.PageName);
                // Do other stuff
            }
            
            
        }
     public class DropdownOptions<T>
     {
         public T Value { get; set; } = default!;
         public string Text { get; set; } = string.Empty;
         public string Icon { get; set; } = string.Empty;
         public string ImageUrl { get; set; } = string.Empty;
         public string PageName { get; set; } = string.Empty;
     }
    }
    HomeDropdownComponent.razor
    @typeparam TValue
    
        
    <MudSelect T="TValue" Label="@Label"  Variant="@Variant" AnchorOrigin="@AnchorOrigin" ValueChanged="OnSelectedValueChanged">
     @foreach (var option in Options)
        {
            <MudSelectItem T="TValue" Value="@(option.Value)">
    
                @if (!string.IsNullOrEmpty(option.Icon))
                {
                    <MudIcon Icon="@option.Icon" Class="mr-2" />
                }
                @if (!string.IsNullOrEmpty(option.ImageUrl))
                {
                    <MudImage Src="@option.ImageUrl" Class="ml-2" />
                }
                @option.Text
            <div style="flex-grow: 1"></div>
    
    
        </MudSelectItem>
        }
    </MudSelect>
    
    HomeDropdownComponent.razor.cs
    
    using Microsoft.AspNetCore.Components;
    using MudBlazor;
     
    
    namespace Test.Shared.Components
    {
        public partial class HomeDropdownComponent<TValue>
        {
            [Parameter]
            public string Label { get; set; } = string.Empty;
    
            [Parameter]
            public string Placeholder { get; set; } = string.Empty;
    
            [Parameter]
            public List<DropdownOptions<TValue>> Options { get; set; } = new();
            [Parameter]
            public DropdownOptions<TValue> SelectedOption { get; set; } = default!;
    
            [Parameter]
    
            public EventCallback<TValue> OnValueChanged { get; set; } = default!;
    
            [Parameter]
            public Variant Variant { get; set; } = Variant.Outlined;
    
            public Origin AnchorOrigin = Origin.BottomCenter;
    
            
            private TValue Value =  default!;
            private async Task OnSelectedValueChanged()
            {
                if (OnValueChanged.HasDelegate)
                    await OnValueChanged.InvokeAsync();
    
            }
           
        }
       
    }
    
    
    
    

    当我运行代码时,默认情况下没有选择任何值,valuechanged函数也返回null。我的要求是,当下拉值更改时,获取页面的值并导航到该页面, 如果我使用 <MudSelect T="TValue" Label="@Label" @bind-Value="SelectedOption.Value" Variant="@Variant" AnchorOrigin="@AnchorOrigin" > 选择第一个下拉值。

    如果使用 <MudSelect T="TValue" Label="@Label" @bind-Value="SelectedOption.Value" Variant="@Variant" AnchorOrigin="@AnchorOrigin" ValueChanged = "OnSelectedValueChanged">

    它显示错误ValueChanged被多次使用。

    1 回复  |  直到 1 年前
        1
  •  0
  •   RBee    1 年前

    Value属性需要分配给 MudSelect

    您需要将更改后的值传递给 EventCallback<TValue> 当您调用它时。

    <MudSelect T="TValue" Label="@Label"  Variant="@Variant"
     AnchorOrigin="@AnchorOrigin" Value="SelectedOption.Value" ValueChanged="OnSelectedValueChanged">
    
    private async Task OnSelectedValueChanged(TValue newValue)
    {
        if (OnValueChanged.HasDelegate)
            await OnValueChanged.InvokeAsync(newValue);
    
    }
    

    如果你没有包装 MudSelect 在另一个组件中,则需要确保分配给的字段 Value 需要在处理程序方法中进行更改。例如。

    private async Task OnSelectedValueChanged(TValue newValue)
    {
        SelectedOption.Value = newValue;
    }
    

    但是,由于它是子组件,因此父组件( HomeDropdownComponent.razor )应该处理更改 SelectedOption.Value .


    这里有一个简化的例子。

    //main.razor
    <HomeDropdownComponent Options="@options"
        TValue="string"
        HomeValue="@parentValue"
        HomeValueChanged="OnHomeValueChanged"/>
    
    <h1>parent chosen value:@parentValue</h1>
    @code{
        string parentValue;
        List<string> options;
        protected  override void OnInitialized()
        {
            options = FetchOptions();
            parentValue = options.First();
        }
        private List<string> FetchOptions()
        {
            return  new List<string>
            {
                "Option 1",
                "Option 2",
                "Option 3",
                "Option 4",
                "Option 5",
            };
        }
        void OnHomeValueChanged(string newVal){
            parentValue=newVal;
        }
    }
    
    //HomeDropdownComponent.razor
    @typeparam TValue
    
    <MudSelect Value="HomeValue" ValueChanged="HandleChange" T="TValue" Variant="Variant.Text" >
        @foreach (var option in Options)
        {
            <MudSelectItem Value="@(option)">
        </MudSelectItem>
        }
    </MudSelect>
    
    <h1>child chosen value:@HomeValue</h1>
    @code{
        [Parameter] public List<string> Options { get; set; } 
        [Parameter] public TValue HomeValue { get; set; } 
        [Parameter] public EventCallback<TValue> HomeValueChanged { get; set; } 
        
    
        async Task HandleChange(TValue newVal){
            await HomeValueChanged.InvokeAsync(newVal);
        }
    }
    

    Demo MudBlazor Snippet