Reputation: 321
I am making a quiz/exam page that uses a Question component. The questions contain answers with either a checkbox or radio selection and a submit button. I need to be able to compare the selected answer(s) to the correct answer when a user clicks submit (or some other button type), but I am not sure how to get the value of the input inside of my @code block for processing.
I've messed around with @bind-value but it doesn't seem to relate to the button click at all and I only want the value from one answer, the selected one.
So far using a "submit" button doesn't seem to be the right route because it does a POST request, which is not the behavior I'm looking for. I just want the button to trigger processing in the component.
Here is my component
<form>
<div class="q-card">
<h3>@Question.QuestionText</h3>
@foreach (var option in Question.Options)
{
<div>
<input type="@Question.InputType" id="@answer" name="@Question.Id" value="@answer"/>
<label for="@answer">@answer</label>
</div>
}
<div class="q-controls">
<button type="submit"@onsubmit="@OnSubmit">Submit</button>
</div>
</div>
</form>
and my @code block
@code {
public string answer;
public void OnSubmit()
{
System.Console.WriteLine(answer);
}
}
I want the value from the selection to end up in the variable answer
when I click Submit. I realize if there are multiple answers (checkbox) I'll need to change this variable, but I'll get to that later.
Upvotes: 5
Views: 12672
Reputation: 41
Here is the code I came up with to implement a radio button group.
<EditForm Model="cleaningModel" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<div class="form-group">
<p class="csCleanedBox">
Cleaned:
</p>
<p class="csLineCondition">
Line Condition: <br />
<input type="radio" id="0" name="Cleaned" value="0" checked="checked" @onclick="(() => { RadioButtonClicked(0); })">
<label for="0">Not Cleaned</label>
</p>
<input type="radio" id="1" name="Cleaned" value="1" @onclick="(() => { RadioButtonClicked(1); })">
<label for="1">1</label>
<input type="radio" id="2" name="Cleaned" value="2" @onclick="(() => { RadioButtonClicked(2); })">
<label for="2">2</label>
<input type="radio" id="3" name="Cleaned" value="3" @onclick="(() => { RadioButtonClicked(3); })">
<label for="3">3</label>
<input type="radio" id="4" name="Cleaned" value="4" @onclick="(() => { RadioButtonClicked(4); })">
<label for="4">4</label>
<input type="radio" id="5" name="Cleaned" value="5" @onclick="(() => { RadioButtonClicked(5); })">
<label for="5">5</label>
</div>
<button class="btn btn-danger" type="button" @onclick="@BackButton">Cancel</button>
<button class="btn btn-primary" type="submit">Submit</button>
<ValidationSummary />
</EditForm>
@Code
{
public class CleaningDto
{
public int Oid { get; set; }
public int Cleaned { get; set; }
}
private readonly CleaningDto cleaningModel = new CleaningDto();
public void RadioButtonClicked(int value)
{
cleaningModel.Cleaned = value;
}
private void Submit()
{
dm.Save(cleaningModel);
}
}
It works like a radio button group should and the class is updated as the user click on a button.
Upvotes: 1
Reputation:
@Collin Brittain, understand that no post back should happen in Blazor. The behavior you're looking for is available. When you click a button, no post back occurs...Blazor is an SPA app where communication with the outside world is possible only through Http calls or via SignalR. However, I'd suggest you to use the the Forms Components provided by Blazor. Those components provide a great deal of functionality, including validation.
The following working sample may help you to resolve your issue:
<form>
<p>@question</p>
@foreach (var item in Enum.GetNames(typeof(Question.Colors)))
{
<div>
<input type="radio" name="question1" id="@item" value="@item" @onchange="SelectionChanged" checked=@(selectedAnswer.Equals(item,StringComparison.OrdinalIgnoreCase)) />
<label for="@item">@item</label>
</div>
}
<div>
<label>Selected answer is @selectedAnswer</label>
</div>
<button type="button" @onclick="@OnSubmit">Submit</button>
</form>
@code {
string selectedAnswer = "";
void SelectionChanged(ChangeEventArgs args)
{
selectedAnswer = args.Value.ToString();
}
Question question = new Question { QuestionText = "What is the color of the sky" };
public void OnSubmit()
{
Console.WriteLine(selectedAnswer);
}
public class Question
{
public string QuestionText { get; set; }
public enum Colors { Red, Green, Blue, Yellow };
}
}
Response to a comment:
This quote is from the Blazor team:
Currently we don't call preventDefault by default on DOM events in most cases. The one exception is for form submit events: in that case, if you have a C# onsubmit handler, you almost certainly don't really want to perform a server-side post, especially given that it would occur before an async event handler.
Later, it's likely that we'll add a syntax for controlling whether any given event handler triggers a synchronous preventDefault
before the event handler runs.
In the following code snippet the form has onsubmit handler, the result of which is that navigation to the about page is prevented, you are on the page where the form resides, and the HandleClick event handler for the button is executed:
<form action="about:blank" @onsubmit=@(() => { })>
<button id="form-1-button" @onclick=HandleClick>Click me</button>
</form>
This code snippet, however, causes the app to navigate to the about page. In other words, the form is submitted. This behavior means that using the button element without assigning the type property is equivalent to using button with type="submit"
<form action="about:blank">
<button id="form-2-button" @onclick="HandleClick">Click me</button>
</form>
In order to prevent navigation to the about page, and execute the HandleClick event handler add the type attribute with the value "button" as done below:
<form action="about:blank">
<button type="button" @onclick="HandleClick" id="form-2-button">Click me</button>
</form>
This code snippet from your question
<button type="submit"@onsubmit="@OnSubmit">Submit</button>
does the following: submit the form instead of calling the OnSubmit event handler of the button element.
Hope this helps...
Upvotes: 10