Home > Software engineering >  (Blazor) Select value not updating
(Blazor) Select value not updating

Time:01-01

I have a <select> element in my page, of which I want to get the value. To do that, I've added the @bind= property. Here's the code:

<form target="#">
    <label for="subject">Vak</label>
    <select @bind="@selectedSubject" id="subject">
        @foreach (Subject subject in Auth.User.Subjects)
        {
            <option value="@subject.Uuid">@subject.Name</option>
        }
    </select><br />
    <!-- (more input fields) -->
<button  @onclick="addNote">Toevoegen</button>
</form>
@code {
    private String selectedSubject { get; set; }
    private String inputTitle { get; set; }
    private String inputContent { get; set; }

    private void addNote()
    {
        Console.WriteLine(selectedSubject);
    }
}

This doesn't output anything, and trying to use selectedSubject results in a NullReferenceError. The other values (inputTitle, inputContent) work as expected.

Yes, the <select> is properly being filled with <option>s.

I've tried switching to whatever <EditForm> is, but it kept giving me warnings and failed to build.

CodePudding user response:

First of all, you don't need a form at all. The main purpose of EditForm is to validate inputs-- like, making sure a password is the correct format.

Also, unless you want to programmatically SET the value of the dropdown, you don't need to bind to it-- instead, use @onchange:

<select @onchange=ProcessSelection>

. . . 

@code {
    Subject SelectedSubject {get; set;}
    async Task ProcessSelection (ChangeEventArgs args){
        SelectedSubject = Auth.User.Subjects.Single(s=>s.uuid = args.Value.ToString();
        // Process the selection.
    }
}

This will (1) give you a place to breakpoint for debugging. (2) Let you do useful things with the SelectedSubject object more easily (like add / remove it from a list, pass it as a parameter to a display component, etc.).

CodePudding user response:

To solve your issue with things not changing, there are two ways you can do it:

  1. Start with a null object for your SelectedSubject, do a null check in your click, and have a dummy select option that forces you to select an item:

.

 <select @onchange=ProcessChange>
    <option selected disabled>Pick a subject. . . </option>
    @foreach (var subject in Auth.User.Subjects) { 
        <option>. . . </option>
    }
</select>
<button @onclick=AddSubject />
    
@code {
    List<Subject> SelectedSubjects = new();
    Subject SelectedSubject {get; set; } = null;
    async Task ProcessChange (ChangeEventArgs args){. . . }
    async Task AddSubject{
       if (Subject is not null) SelectedSubjects.Add (SelectedSubject);
    }
}
  1. Preselect your first option in your data initialization, and then you don't NEED the dummy <option> or the null check.

.

@code{
    async Task OnInitializedAsync (bool IsFirstRender){
        Auth.User.Subjects = await LoadSubjectsForUser (Auth.User);
        SelectedSubject = Auth.User.Subjects.First();
    }
}

In your use case, I think #1 is probably better.

  • Related