简体   繁体   中英

Why radio button is selected on Next/Previous buttons click

Below is the sample.

I am trying to show questions on Next/Previous.

Below is the blazor web page.

Which has C# code & HTML.

@page "/Quiz"


    <table class="table">

        <thead>
            <tr>
                <th>
                    <h3>Question : @currentCount.ToString()</h3>
                </th>
            </tr>
        </thead>

        <tbody>
            @foreach (var question in exam.Questions.Where(x => x.Id == currentCount.ToString()))
            {
                <tr>
                    <th>
                        <h3>@question.Text</h3>
                    </th>
                </tr>

                @foreach (var choice in question.Choices)
                {
                    <tr>
                        <th>
                            <label>
                                <input type="radio" name="@question.Id" value="@question.Id" />
                                @choice.Text
                            </label>

                        </th>
                    </tr>
                }
            }
        </tbody>

    </table>

    <button class="btn btn-primary" @onclick="NextQuestion">Next</button>

    <button class="btn btn-primary" @onclick="PreviousQuestion">Previous</button>

    @code {


        Model.Exam exam = new Model.Exam();
        private int currentCount = 1;

        protected override void OnInitialized()
        {
            exam.Id = "1";
            exam.Questions = new List<Model.Question>();

            Model.Question question1 = new Model.Question();
            question1.Id = "1";
            question1.Text = "Which data type is used to create a variable that should store text?";

            Model.Choice choice1 = new Model.Choice();
            choice1.Id = "1";
            choice1.Text = "Txt";

            Model.Choice choice2 = new Model.Choice();
            choice2.Id = "2";
            choice2.Text = "str";


            Model.Choice choice3 = new Model.Choice();
            choice3.Id = "3";
            choice3.Text = "myString";

            Model.Choice choice4 = new Model.Choice();
            choice4.Id = "4";
            choice4.Text = "string";

            question1.Choices = new List<Model.Choice>() { choice1, choice2, choice3, choice4 };
            exam.Questions.Add(question1);

            Model.Question question2 = new Model.Question();

            question2.Id = "2";
            question2.Text = "Which property can be used to find the length of a string?";

            choice1 = new Model.Choice();
            choice1.Id = "1";
            choice1.Text = "getLength()";

            choice2 = new Model.Choice();
            choice2.Id = "2";
            choice2.Text = "length";

            choice3 = new Model.Choice();
            choice3.Id = "3";
            choice3.Text = "Length";

            choice4 = new Model.Choice();
            choice4.Id = "4";
            choice4.Text = "length()";

            question2.Choices = new List<Model.Choice> { choice1, choice2, choice3, choice4 };
            exam.Questions.Add(question2);

        }

        private void NextQuestion()
        {
            currentCount++;

        }

        private void PreviousQuestion()
        {
            currentCount--;
        }
    }

When I try to show all questions in single page. It's working.

I used different name for radio buttons.

What could be the issue. Did I miss anything?

Is it the correct design what I am doing?

I am using blazor web assembly.

Your solution was pretty much working. Only a few things needed to be changed.

You could change the name of your field currentCount to something like questionIndex and starting with zero. In the view, you get a single question then by its index like <h3>@exam.Questions[questionIndex].Text</h3> .

The radio button then gets kind of tricky.

<input type="radio" 
   name="@exam.Questions[questionIndex].Id" 
   value="@choice.Id" 
   @onchange="SelectionChanged" 
   checked="@(exam.Questions[questionIndex].SelectedChoiceId == choice.Id)"
   @key="@(exam.Questions[questionIndex].Id + choice.Id)" />

To update the model, we introduce a method handler for the change event and update the property SelectedChoiceId of the Question .

void SelectionChanged(ChangeEventArgs args)
{
   exam.Questions[questionIndex].SelectedChoiceId = (String)args.Value;
}

In case a user navigates back and forth, it would be nice to pre-select the input. So, we set the checked property to true if the option is selected.

The @key attribute controls when Blazor reuses a component. As long as the value of the @key doesn't change, Blazor assumes that the element is the same. In this case, the key is changed every time a user navigates, which forces Blazor to rerender the entire radio button. This resets the "checked" state that is saved by some browsers.

Putting everything together results in

@page "/Quiz"


<table class="table">
    <thead>
        <tr>
            <th>
                <h3>Question : @((questionIndex+1).ToString())</h3>
            </th>
        </tr>
    </thead>
    <tbody>
            <tr>
                <th>
                    <h3>@exam.Questions[questionIndex].Text</h3>
                </th>
            </tr>
            @foreach (var choice in @exam.Questions[questionIndex].Choices)
            {
                <tr>
                    <th>
                        <label>
                            <input  type="radio" 
                                   name="@exam.Questions[questionIndex].Id" 
                                   value="@choice.Id" 
                                   @onchange="SelectionChanged" 
                                   checked="@(exam.Questions[questionIndex].SelectedChoiceId == choice.Id)"
                                   @key="@(exam.Questions[questionIndex].Id + choice.Id)" 
                                   />
                            @choice.Text
                        </label>
                    </th>
                </tr>
            }
    </tbody>
</table>


<button class="btn btn-primary" @onclick="NextQuestion">Next</button>
<button class="btn btn-primary" @onclick="PreviousQuestion">Previous</button>

@code {

    private Model.Exam exam = new Model.Exam();
    private int questionIndex = 0;

    private void NextQuestion()
    {
        //keeo boundaries in mind
        questionIndex++;
    }

    private void PreviousQuestion()
    {
        //keep boundaries in mind
        questionIndex--;
    }

    void SelectionChanged(ChangeEventArgs args)
    {
        exam.Questions[questionIndex].SelectedChoiceId = (String)args.Value;
    }

    protected override void OnInitialized()
    {
        //not changed
        //...
    }
}


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM