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:
- Start with a null object for your
SelectedSubject
, do a null check in your click, and have a dummyselect
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);
}
}
- 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.